多进程DP

hdu  2686

找两条从(1,1)到(n,n)的路径,使得权值最大,且节点不重叠

让两个进程同时进行。枚举步数,当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)) + map(x1, y1) + map(x2, y2) ; 


但是因为只能往右或者往下,所以坐标满足x+y=k+2(这里是下标从1开始,如果下标从0开始则是x+y=k);

这样方程可以降为3维


dp(k, x1, x2) = max(dp(k-1, x1-1, x2-1), dp(k-1, x1-1,x2), dp(k-1, x1, x2-1), dp(k-1, x1,x2)) + map(x1, k-x1) + map(x2, k-x2) ; 

【也就是从以下上一步的情况选出最大的:A下B下。。A下B右。。A右B下。。A右B右】

当x1==x2||y1==y2时只加上一个目前的格子中的财富。


zzulioj


主要注意按照1-n存储的话,x+y=k-2;

按照0-n-1存储的话x+y=k;

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define maxx(a,b,c,d)  max(max(a,b),max(c,d))
int n,m;
int map[105][105];
int dp[205][105][105];


int main(){
	int T;
	//freopen("2.txt","r",stdin);
	scanf("%d",&T);
	while(T--){
		memset(map,0,sizeof(dp));	
		memset(dp,0,sizeof(dp));	
		
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				scanf("%d",&map[i][j]);
			}
		}
		dp[0][1][1]=map[1][1];//注意第一步 
		//x+y=k+2;
		
		for(int k=1; k<=n+m-2; k++){
			for(int i=1; i<=k+1; i++){
				for(int j=1; j<=k+1; j++){
					dp[k][i][j]=maxx(dp[k-1][i-1][j],dp[k-1][i][j-1],dp[k-1][i-1][j-1],dp[k-1][i][j]);
					if(i==j){
						dp[k][i][j]+=map[i][k+2-i];
					}
					else{
						dp[k][i][j]+=map[i][k+2-i]+map[j][k+2-j];
					}
				}
			}
		}		
		printf("%d\n",dp[m+n-2][n][n]);
	}
	return 0;
} 







你可能感兴趣的:(多进程DP)