藍橋杯 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;	
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章