[蓝桥杯][2014年第五届真题]地宫取宝

   日期:2020-10-10     浏览:93    评论:0    
核心提示:题目链接:地宫取宝解题思路:动态规划。在每一个位置的状态考虑,当前这个位置的状态是由哪些状态转移过来的。dp[i][j][u][v]表示在(i,j)这个位置,拿到u个物品,且这些物品的最大价值是v。我们可以考虑当前位置(i,j)拿不拿当前这个物品,如果不拿那么可以从dp[i-1][j][u][v]、dp[i][j-1][u][v]转移过来,表示上一个位置已经拿到了u个物品最大价值为v的。如果拿则可以从dp[i-1][j][u-1][c]、dp[i][j-1][u-1][c]转移过来,表示上一个

题目链接:地宫取宝



解题思路:动态规划。在每一个位置的状态考虑,当前这个位置的状态是由哪些状态转移过来的。


dp[i][j][u][v]表示在(i,j)这个位置,拿到u个物品,且这些物品的最大价值是v。


我们可以考虑当前位置(i,j)拿不拿当前这个物品,如果不拿那么可以从dp[i-1][j][u][v]、dp[i][j-1][u][v]转移过来,表示上一个位置已经拿到了u个物品最大价值为v的。如果拿则可以从dp[i-1][j][u-1][c]、dp[i][j-1][u-1][c]转移过来,表示上一个位置拿了u-1个,并且最大价值为c(c为小于v的数),最后再把最后手上可能拿的价值的方案数加起来即可。


ps:因为这道题的所有物品价值范围是0…120…12,可以把他们全部都递增,范围就变成了1…131…13,因为我们记录的是方案数,只关心各个物品之间的大小关系,具体数值不影响答案,但是这样的做法可以把00作为一个特殊边界来处理

#include<bits/stdc++.h>
#define x first
#define y second
#define mem(h) memset(h,-1,sizeof h)
#define mcp(a,b) memcpy(a,b,sizeof b)
using namespace std;
typedef long long LL;
typedef unsigned long long ull; 
typedef pair<int,int>PII;
typedef pair<double,double>PDD;
namespace IO{ 
	inline LL read(){ 
		LL o=0,f=1;char c=getchar();
		while(c<'0'||c>'9'){ if(c=='-')f=-1;c=getchar();}
		while(c>='0'&&c<='9'){ o=o*10+c-'0';c=getchar();}
		return o*f;
	}
}using namespace IO;
//#############以上是自定义技巧(可忽略)########## 
const int N=50+7,M=2e5+7,INF=0x3f3f3f3f,mod=1e9+7,P=131;
int dp[N][N][13][14]; 
int n,m,k;
int w[N][N];
int main(){ 
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++){ 
		for(int j=1;j<=m;j++){ 
			cin>>w[i][j];
			w[i][j]++;//这里是需要注意的点,把所有的权值+1,更好处理也不影响结果
		}
	}
	dp[1][1][1][w[1][1]]=1;//如果拿起(1,1)的物品
	dp[1][1][0][0]=1;//如果不拿
	for(int i=1;i<=n;i++){ 
		for(int j=1;j<=m;j++){ 
			if(i==1&&j==1)continue;//这个位置可以跳过
			for(int u=0;u<=k;u++){ //枚举到达当前位置可能拿了几个物品
				for(int v=0;v<=13;v++){ //枚举到达当前位置手中的最大物品价值
					int &val=dp[i][j][u][v];
					val=(val+dp[i-1][j][u][v])%mod;//不拿当前位置的物品时可能从这些状态转移过来
					val=(val+dp[i][j-1][u][v])%mod;
					if(u>0&&v==w[i][j]){ //如果到达当前位置手中有物品,并且物品最大价值等于当前位置的物品价值,那么可以拿起当前物品
						for(int c=0;c<v;c++){ //可以从这些状态转移过来
							val=(val+dp[i-1][j][u-1][c])%mod;
							val=(val+dp[i][j-1][u-1][c])%mod;
						}
					} 
				}
			}
		}
	}
	int res=0;
	for(int i=0;i<=13;i++){ 
		res=(res+dp[n][m][k][i])%mod;//把最后手上可能拿的最大价值方案数相加
	}
	cout<<res<<endl;
	return 0;
}
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服