直接DP,做完看别人说是用类似于双调欧几里得旅行商问题一样的方法解,仔细一看我的代码,貌似也和那旅行商问题做法差不多~~
这题坑爹之处在于,不能用floyd去优化,也就是说说好了从a到c是99,然后你不能靠先到b再到c来优化。。
View Code
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 int cos[50][50],dp[2][33][33][33]; 6 struct data 7 { 8 int x,y,z; 9 data() {} 10 data(int _x,int _y,int _z) 11 { 12 x=_x; 13 y=_y; 14 z=_z; 15 } 16 }Q[200000]; 17 int main() 18 { 19 int T; 20 for(scanf("%d",&T); T; T--) 21 { 22 int n; 23 scanf("%d",&n); 24 memset(cos,-1,sizeof(cos)); 25 for(int i=1; i<n; i++) 26 { 27 cos[i][i]=0; 28 for(int j=i+1; j<=n; j++) 29 { 30 scanf("%d",&cos[i][j]); 31 cos[j][i]=cos[i][j]; 32 } 33 } 34 cos[n][n]=0; 35 memset(dp,-1,sizeof(dp)); 36 dp[0][1][1][1]=0; 37 int st,ed; 38 st=ed=0; 39 Q[ed++]=data(1,1,1); 40 for(int t=2; t<=n; t++) 41 { 42 int x=t&1,y=x^1; 43 int i=ed; 44 while(st!=i) 45 { 46 data a=Q[st++]; 47 if(st==200000) 48 st=0; 49 int tp=dp[x][a.x][a.y][a.z]; 50 int fp=dp[y][t][a.y][a.z]; 51 if(fp==-1||fp>tp+cos[a.x][t]) 52 { 53 dp[y][t][a.y][a.z]=tp+cos[a.x][t]; 54 if(fp==-1) 55 { 56 Q[ed++]=data(t,a.y,a.z); 57 if(ed==200000) 58 ed=0; 59 } 60 } 61 fp=dp[y][a.x][t][a.z]; 62 if(fp==-1||fp>tp+cos[a.y][t]) 63 { 64 dp[y][a.x][t][a.z]=tp+cos[a.y][t]; 65 if(fp==-1) 66 { 67 Q[ed++]=data(a.x,t,a.z); 68 if(ed==200000) 69 ed=0; 70 } 71 } 72 fp=dp[y][a.x][a.y][t]; 73 if(fp==-1||fp>tp+cos[a.z][t]) 74 { 75 dp[y][a.x][a.y][t]=tp+cos[a.z][t]; 76 if(fp==-1) 77 { 78 Q[ed++]=data(a.x,a.y,t); 79 if(ed==200000) 80 ed=0; 81 } 82 } 83 } 84 memset(dp[x],-1,sizeof(dp[x])); 85 } 86 int ans=1<<30,t=(n+1)&1; 87 while(st!=ed) 88 { 89 data tmp=Q[st++]; 90 if(st==200000) 91 st=0; 92 ans=min(ans,dp[t][tmp.x][tmp.y][tmp.z]); 93 } 94 printf("%d\n",ans); 95 } 96 return 0; 97 }