TOPOI 测验1320, 问题C: 4410: [CF41D]Pawn 题解

题目链接

题目大意

在一个树阵中按一定走法取一些树,使和最大且被 k+1整除

解题思路

类似一个数塔问题

因为最后的结果要被 k+1 整除,所以可以记录到每一个点  对 k+1 取余结果不同的最优解(最大值),不用记录每一个数,浪费空间和时间

举个例子:

当到达 (i, j) 这个点时,有两种路线得到的值分别为a, b(a>b),且a % (k+1) = x, b % (k+1) = x,那么此时只需记录a,将b舍去

因为余数相同不会对后面的结果产生影响

最后枚举最后一行对 k+1取余结果为0的结果,取最大值

空间 n*m*k, 时间n*m*k

代码

很短很简单

#include <bits/stdc++.h>
using namespace std;
int n, m, k, a[105][105], num[105][105][15], ans = -1;
char ch;
int main(){
	scanf ("%d %d %d", &n, &m, &k); k++;
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= m; j++)  
	    cin >> ch, a[i][j] = ch -'0';
	memset (num, -1, sizeof (num));
	for (int i = 1; i <= m; i++)  num[1][i][a[1][i]%k] = a[1][i];
	for (int i = 2; i <= n; i++)
	  for (int j = 1; j <= m; j++)
	  	for (int p = 0; p < k; p++) {
	  		int t = (p + a[i][j]) % k;
	  		if (j != 1 and num[i-1][j-1][p] > 0)  num[i][j][t] = num[i-1][j-1][p] + a[i][j];
	  		if (j != m and num[i-1][j+1][p] > 0)  num[i][j][t] = max (num[i][j][t], num[i-1][j+1][p] + a[i][j]);
	    } 
	for (int i = 1; i <= m; i++) ans = max (ans, num[n][i][0]);
	printf ("%d", ans);
	return 0;
} 

  

猜你喜欢

转载自www.cnblogs.com/whx666/p/10633305.html