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

题目链接:

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

思路:

1.记 d p [ i ] [ j ] [ a ] [ b ] dp[i][j][a][b] dp[i][j][a][b]为走到坐标为 ( i , j ) (i,j) (i,j)位置后,手上有 a a a件物品且所有物品中最大值为 b b b的方案数;
2.假设我们现在从 ( a , b ) (a,b) (a,b)走到 ( x , y ) (x,y) (x,y)(这两个位置相邻),记 v [ i ] [ j ] v[i][j] v[i][j]是处在坐标为 ( i , j ) (i,j) (i,j)的物品的价值,那么到 ( x , y ) (x,y) (x,y)可以选择不取该位置的物品,如果该位置物品大于 ( a , b ) (a,b) (a,b)处物品的最大值、那么也可以选择取此处的物品;
复杂度 O ( n m k C ) 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;	
}

猜你喜欢

转载自blog.csdn.net/qq_45228537/article/details/105220459
今日推荐