大楼(bzoj 2165)
Description
xz是一個旅游愛好者,這次他來到了一座新的城市。城市中央有一幢高聳入云的大樓。這幢樓到底有多少層呢?據說和非負整數的個數是一樣多的。xz想爬上這座大樓來觀賞新城市的全景。這幢大樓的樓層從下至上用從小到大的非負整數編號。每層樓有n個房間,用1到n的正整數編號。樓層之間用電梯連接,電梯只能上行,不能下行或者同層移動。(下樓一般自行解決)電梯用(u,v,w)的形式給出,表示對于任意正整數i,有第i層的房間u到第i+w層的房間v有一部電梯。電梯只能從起點開往終點,不能中途停留。 xz想要觀賞城市全景,至少需要登上第m層樓,即最終需要到達的樓層數≥m。由于乘坐電梯要繳納高額的費用,而如果花銷太大回家就沒法報賬了,xz希望乘坐電梯的次數最少。現在xz在第0層的1號房間,你需要求出這個最少的乘坐次數。
Input
第一行包含一個正整數T,表示數據的組數。接下來的數據分為T個部分。每個部分第一行包含兩個正整數n和m,意義見題目描述。接下來n行,每行包含n個非負整數。這n行中,第i行第j個數為Wi,j,如果wi,j非零,則表示有電梯(i,j,Wi,j)。同一行各個數之間均用一個空格隔開。
Output
對于每組數據,輸出一行一個正整數,最少的乘坐次數。
Sample Input
26 147
0 1 0 50 0 0
0 0 1 0 0 0
20 0 0 0 0 0
0 0 0 0 1 50
0 0 0 8 0 0
0 0 0 0 0 3
6 152
0 1 0 50 0 0
0 0 1 0 0 0
20 0 0 0 0 0
0 0 0 0 1 50
0 0 0 8 0 0
0 0 0 0 0 3
Sample Output
910
【樣例說明】
第一組數據中,使用電梯的順序為1→2→3→1→2→3→1→4→6→6;第二組數據中,使用電梯的順序為1→2→3→1→2→3→1→4→5→4→6。第二組數據最后到達了153層,但是沒有更短的路徑使得恰好到達152層,因此答案為10。
HINT
有如下幾類具有特點的數據: 1、有10%的數據所有的n=2; 2、有20%的數據m≤3000; 3、有20%的數據對于滿足1≤i,j≤n的整數i和j,若wi,j≠0,則有wi,j≥1015; 4、有30%的數據所有的n=40。以上各類數據均不包含其他類數據。對于所有數據T=5,1≤n≤100,1≤m≤1018;對于滿足1≤i,j≤n的整數i和j,有0≤wi,j≤1018。數據保證能夠到達m層或更高的樓層。
/*f[p][i][j]表示用了p次電梯,從i房間到j房間的最高樓層。f[p][i][j]=max(f[p/2][i][k],f[p/2][k][j])然后用矩陣乘法算f[2],f[4],f[8]... 直到某個f第一行出現大于m的數。然后用二進制拆分求出答案。 */ #include<cstdio> #include<iostream> #include<cstring> #define N 110 #define lon long long #define inf 1000000000000000000LL using namespace std; int n,cnt; lon m; lon read(){lon num=0,flag=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}return num*flag; } struct M{lon v[N][N];M(){memset(v,0,sizeof(v));} }f[N]; M operator*(M a,M b){M c;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){c.v[i][j]=-inf;for(int k=1;k<=n;k++)c.v[i][j]=max(a.v[i][k]+b.v[k][j],c.v[i][j]);if(c.v[i][j]>m) c.v[i][j]=m;}return c; } bool check(M x){for(int i=1;i<=n;i++)if(x.v[1][i]>=m) return true;return false; } int main(){int T;scanf("%d",&T);while(T--){n=read();m=read();for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){f[1].v[i][j]=read();if(!f[1].v[i][j]) f[1].v[i][j]=-inf;}for(cnt=1;;cnt++){f[cnt+1]=f[cnt]*f[cnt];if(check(f[cnt+1])) break;}M t=f[1];lon ans=1;for(int i=cnt;i;i--){M x=t*f[i];if(!check(x)){for(int j=1;j<=n;j++)for(int k=1;k<=n;k++)t.v[j][k]=x.v[j][k];ans+=1LL<<(i-1);}}cout<<ans+1<<endl;}return 0; }?
轉載于:https://www.cnblogs.com/harden/p/6643500.html
總結
以上是生活随笔為你收集整理的大楼(bzoj 2165)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android Studio 设置字体
- 下一篇: LoadRunner如何调用外部函数