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