http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2901
一般DP复杂度 O(L*N^2), 分段计算 O(lgL*N*N)
View Code
#include <iostream> #include <cstdio> #include <vector> #include <queue> #include <map> #include <string> #include <cstring> #include <algorithm> int f_min(int x,int y) {if(x>y) return y; else return x;} int f_max(int x,int y) {if(x>y) return x; else return y;} using namespace std; const int MM = 1111111; //typedef __int64 int64; typedef long long int64; //const __int64 maxint = 0x3f3f3f3f; const long long maxint = 10000000000000; string str[MM]; int64 N,M,L; int64 maze[111][111]; int64 d[2][111]; int64 dp[20][111][111]; void get_data() { int64 i,j,k; scanf("%lld%lld",&N,&L); for(i=1;i<=N;i++) { for(j=1;j<=N;j++) { scanf("%lld",&dp[0][i][j]); } } L--; } void debug(int len) { int i,j,k; for(i=0;i<=len;i++) { printf("%d\n",i); for(j=1;j<=N;j++) { for(k=1;k<=N;k++) { printf("%d ",dp[i][j][k]); } printf("\n"); } } } void solve() { int64 i,j,k,t; int64 now=0, pre=1, len=0; for(i=0;(1<<(i+1))<=L;i++) { for(j=1;j<=N;j++) { for(k=1;k<=N;k++) { dp[i+1][j][k]=-maxint; for(t=1;t<=N;t++) { if((dp[i][j][t]+dp[i][t][k])>dp[i+1][j][k]) { dp[i+1][j][k]=dp[i][j][t]+dp[i][t][k]; } } } } len++; } // debug(len); memset(d[now],0,sizeof(d[now])); for(i=len;i>=0;i--) { if(L < (1<<i)) continue; L-=(1<<i); for(j=1;j<=N;j++) d[pre][j]=-maxint; for(j=1;j<=N;j++) { for(k=1;k<=N;k++) { if(d[pre][k]<(d[now][j]+dp[i][j][k])) d[pre][k]=d[now][j]+dp[i][j][k]; } } now=pre, pre^=1; } int64 ans=-maxint; for(i=1;i<=N;i++) { if(d[now][i]>ans) ans=d[now][i]; } printf("%lld\n",ans); } int main() { int ca; scanf("%d",&ca); while(ca--) get_data(),solve(); return 0; }