蓝桥杯 PREV-28 地宫取宝(dp)

题目链接:

http://lx.lanqiao.cn/problem.page?gpid=T120

思路:

1.记dp[i][j][a][b]dp[i][j][a][b]为走到座标为(i,j)(i,j)位置后,手上有aa件物品且所有物品中最大值为bb的方案数;
2.假设我们现在从(a,b)(a,b)走到(x,y)(x,y)(这两个位置相邻),记v[i][j]v[i][j]是处在座标为(i,j)(i,j)的物品的价值,那么到(x,y)(x,y)可以选择不取该位置的物品,如果该位置物品大于(a,b)(a,b)处物品的最大值、那么也可以选择取此处的物品;
复杂度O(nmkC)O(nmkC)

代码:

#include<bits/stdc++.h>

using namespace std;

const int mod = 1000000007;
int n, m, k, v[55][55];
int dp[55][55][15][15];

#define f(a, b) a = (a + b) % mod;
inline void check(int a, int b, int & x, int & y) {
	if(a <= 0 || b <= 0) return;
	for(int	i = 0; i <= k; i++) {
		for(int j = 0; j <= 13; j++) {
			f(dp[x][y][i][j], dp[a][b][i][j]);
			if(v[x][y] > j) f(dp[x][y][i + 1][v[x][y]], dp[a][b][i][j]);
		}
	}
}

int main() {
#ifdef MyTest
	freopen("Sakura.txt", "r", stdin);
#endif
	scanf("%d %d %d", &n, &m, &k);
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			scanf("%d", &v[i][j]);
			++v[i][j];	
		}
	}
	dp[1][1][0][0] = 1;
	dp[1][1][1][v[1][1]] = 1;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			check(i - 1, j, i, j);
			check(i, j - 1, i, j);
		}
	}
	int ans = 0;
	for(int i = 1; i <= 13; i++) f(ans, dp[n][m][k][i]);
	printf("%d", ans);
	return 0;	
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章