Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1005 Accepted Submission(s): 558
多进程DP,昨天第一次听说...
题目大意是找两条从(1, 1) 到(n, n)的路径,使权值和最大且节点不重叠。
让两个进程同时进行,枚举步数K,当x1==x2||y1==y2时跳过,得状态转移方程:
dp(k, x1, y1, x2, y2) = max(dp(k-1, x1-1, y1, x2-1, y2), dp(k-1, x1-1, y1, x2, y2-1), dp(k-1, x1, y1-1, x2-1, y2), dp(k-1, x1, y1-1,x2, y2-1))
+ data(x1, y1) + data(x2, y2) ;
由于只能走右或下,所以坐标满足x+y=k。这样就能降低维数为3维,方程:
dp(k, x1, x2) = max(dp(k-1, x1, x2), dp(k-1, x1-1, x2), dp(k-1, x1, x2-1), dp(k-1, x1-1, x2-1)) + data(x1, k-x1) + data(x2, k-x2) ;
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 6 using namespace std; 7 8 int data[40][40],dp[80][40][40]; 9 10 int Max(int a,int b,int c,int d){ 11 return max(a,max(b,max(c,d))); 12 } 13 14 int main(){ 15 16 //freopen("input.txt","r",stdin); 17 18 int n; 19 while(~scanf("%d",&n)){ 20 int i,j,k; 21 for(i=0;i<n;i++) 22 for(j=0;j<n;j++) 23 scanf("%d",&data[i][j]); 24 memset(dp,0,sizeof(dp)); 25 for(k=1;k<2*n-2;k++) 26 for(i=0;i<n;i++) 27 for(j=0;j<n;j++){ 28 if(i==j) 29 continue; 30 dp[k][i][j]=Max(dp[k-1][i][j],dp[k-1][i-1][j],dp[k-1][i][j-1],dp[k-1][i-1][j-1]); 31 dp[k][i][j]+=data[i][k-i]+data[j][k-j]; 32 } 33 int ans=max(dp[k-1][n-1][n-2],dp[k-1][n-2][n-1])+data[0][0]+data[n-1][n-1]; 34 printf("%d\n",ans); 35 } 36 return 0; 37 }