Vijos P1143 三取方格數(動態規劃,多進程DP)

P1143三取方格數

背景

JerryZhou同學經常改編習題給自己做。

這天,他又改編了一題。。。。。

描述

設有N*N的方格圖,我們將其中的某些方格填入正整數,
而其他的方格中放入0。

某人從圖得左上角出發,可以向下走,也可以向右走,直到到達右下角。

在走過的路上,他取走了方格中的數。(取走後方格中數字變爲0)
此人從左上角到右下角共走3次,試找出3條路徑,使得取得的數總和最大。

格式

輸入格式

第一行:N (4<=N<=20)
接下來一個N*N的矩陣,矩陣中每個元素不超過80,不小於0

輸出格式

一行,表示最大的總和。

樣例1

樣例輸入1[複製]

4
1 2 3 4
2 1 3 4
1 2 3 4
1 3 2 4

樣例輸出1[複製]

39

限制

各個測試點1s

提示

多進程DP

思路

從左上角到右下角,分三次取數,求最大和。每一條路徑可以向下,也可以向右,有兩個方向,也就是一共有八種情況(2^3)
如果用f[x1][y1][x2][y2][x3][y3]來表示不同路徑的最大值,則有20*20*20*20*20*20,不論在時間還是空間上都不允許。

考慮到不同路徑在經過相同步數時,一定存在x1+y1==x2+y2==x3+y3,就可以通過計算求y2,y3

代碼

#include <iostream>
#define N 22
using namespace std;
int i,j,n,x1,y1,x2,y2,x3,y3,u,v,w,z;
int a[N][N],f[N][N][N][N];
int main()
{
	cin>>n;
	for(i=1;i<=n;i++)
	  for(j=1;j<=n;j++)
	    cin>>a[i][j];
	for(x1=1;x1<=n;x1++)
	  for(y1=1;y1<=n;y1++)
	    for(x2=1;x2<=x1;x2++)
	      for(x3=1;x3<=x1;x3++)
	      {
				y2=x1+y1-x2;
				y3=x1+y1-x3;
				u=max(f[x1-1][y1][x2][x3],f[x1-1][y1][x2][x3-1]);		//求八個不同路徑所有取得的最大值 
				v=max(f[x1-1][y1][x2-1][x3],f[x1-1][y1][x2-1][x3-1]);	
				w=max(f[x1][y1-1][x2][x3],f[x1][y1-1][x2][x3-1]);
				z=max(f[x1][y1-1][x2-1][x3],f[x1][y1-1][x2-1][x3-1]);
				f[x1][y1][x2][x3]=max(max(u,v),max(w,z))+a[x1][y1];		//加上第一個數 
				if(x1!=x2&&y1!=y2)
				  f[x1][y1][x2][x3]+=a[x2][y2];							//加上第二個數 
				if(x1!=x3&&y1!=y3&&x2!=x3&&y2!=y3)
				  f[x1][y1][x2][x3]+=a[x3][y3];							//加上第三個數 
		  }
	cout<<f[n][n][n][n]<<endl;
	return 0;
}


發佈了56 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章