NOIP 2000 方格取数 NOIP 2008 传纸条 多线程DP

这两道DP基本是一样的,相隔8年的noip出了同样的题也是奇怪。

COGS 和TYVJ 上都可以找到这两道题,直接搜题名即可。


都很简单,我是先写的传纸条,后来才发现的方格取数这道题,于是直接粘了代码。

我们先来说传纸条:

有来、回两次行走,而且不能有路径交叉。我们可以转换为一次行走,有两个人同时行走,形象地说为多线程。只要每一时刻都保证两个人不在同一点上就可以保证路径不会交叉(这个仔细想想或者画一画就可以证明是对的)。那么状态表示可以是f[i][j][k][l]表示第一个人在(i,j)第二个人在(k,l)时的最优解。但是,因为两个人是同时走的,所以这个四维的数组会有很多浪费的空间。

我们可以把它变成三维的,f[i][j][k]表示在第i步,第一个人在第j行,第二个人在第k行时的最优解,这样仍然可以确定每个状态下两个人的坐标。

状态转移一共有四种(在全部合法的情况下,如果从两个人走到一个相同的点转移到现状态肯定就是不合法的):

f[i][j][k] = max(f[i-1][j][k],f[i-1][j-1][k-1],f[i-1][j-1][k],f[i-1][j][k-1])+a[j][i-j+1]+a[k][i-k+1];

其实这种状态以及转移与很多人所说的对角线本质是相同的,第i步就相当于第i条对角线,保证状态合法的判断都是j < k(或j != k)。两者相同的是,要小心边界,边界一不小心处理不好就会WA。在我的描述中,因为i表示的是第i步,所以j,k <= i,所以就是代码中的j,k <= min(i,n),这是很重要的,如果仅仅是j,k <= n会出错,因为这样的话,不合法的状态就不只是j==k的状态,还有j > i以及k > i这样的实际不存在的状态,我一开始就因为这个WA了一次。

#include 
#include 
#include 
using namespace std;

int n, m, a[51][51], f[101][51][51];

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+m-1; i++)
	for(int j = 1; j <= min(i, n); j++)
	for(int k = 1; k <= min(i, n); k++){
		if(j != k) f[i][j][k] = max(f[i-1][j][k], f[i-1][j-1][k-1]);
		if(j-1 != k) f[i][j][k] = max(f[i-1][j-1][k], f[i][j][k]);
		if(j != k-1) f[i][j][k] = max(f[i-1][j][k-1], f[i][j][k]);
		f[i][j][k] += a[j][i-j+1]+a[k][i-k+1]; 
	}
	
	printf("%d", f[n+m-1][n][n]);
}

先写了传纸条后在讨论区发现了方格取数,于是也就去看了看,就变得异常简单了:只需要把j == k的时候改变一下就可以,只需防止它把同一个点的值加两遍即可。

#include 
#include 
#include 
using namespace std;

int n, a[11][11], f[21][11][11];

int main()
{
	scanf("%d", &n);
	int t1, t2, t;
	while(scanf("%d %d %d", &t1, &t2, &t) && t)
		a[t1][t2] = t;
	
	for(int i = 1; i <= n+n-1; i++)
	for(int j = 1; j <= min(i,n); j++)
	for(int k = 1; k <= min(i,n); k++){
		f[i][j][k] = max(f[i-1][j][k], f[i-1][j-1][k-1]);
		f[i][j][k] = max(f[i-1][j-1][k], f[i][j][k]);
		f[i][j][k] = max(f[i-1][j][k-1], f[i][j][k]);	
		f[i][j][k] += a[j][i-j+1] + a[k][i-k+1]*(j!=k);
	}
	
	printf("%d", f[n+n-1][n][n]);
}

你可能感兴趣的:(NOIP 2000 方格取数 NOIP 2008 传纸条 多线程DP)