P1006

传纸条

题目大意:找两条不重复的路径使得相加最大

做法:两条路不重复dp

#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn = 51;
int n,m,a[maxn][maxn],dp[maxn][maxn][maxn][maxn];

int Max(int a,int b,int c,int d)
{
	return max(max(a,b),max(c,d));
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			scanf("%d",&a[i][j]);
	for(int i=1;i<=n;i++)
		for(int j=1;j<m;j++)
			for(int k=1;k<n;k++)
				for(int l=j+1;l<=m;l++)
					dp[i][j][k][l] = Max
					(dp[i-1][j][k-1][l],dp[i][j-1][k-1][l]
					,dp[i-1][j][k][l-1],dp[i][j-1][k][l-1])
					+ a[i][j] + a[k][l];
	printf("%d",dp[n][m-1][n-1][m]);
	return 0;
}

精髓之处

          for(int i=1;i<=n;i++)
		for(int j=1;j<m;j++)
			for(int k=1;k<n;k++)
				for(int l=j+1;l<=m;l++)

他可以保证一定不会重复

说明:\(i\),\(j\)的终点是第\(n\)行,第\(m-1\)列,\(k\),\(l\)的终点是第\(n-1\)行,第\(m\)列,两个的终点不一样所以只需要保证中间过程没有重复就好。所以\(j\)只循环到\(m-1\)\(k\)只循环到\(n-1\),而要使得他们分开,只需要让他们的行不一样或列不一样即可,所以让\(l\)\(j+1\)开始循环就能错开列,这样也就能保证两条路径并不会有重复。