您的位置:首页 > 其它

ZCMU—1601

2016-12-30 05:40 183 查看

1601: 卡斯丁狗去挖矿

Time Limit: 3 Sec  Memory Limit: 128 MB

[Submit][Status][Web
Board]

Description

 最近卡斯丁狗和他的好基友Tomcat在玩《我的世界》这款游戏。在游戏中玩家可以用各种材料搭建房屋,制造铁路线,制造炸弹,晚上还可以打僵尸等等。然而在这之前最最重要的就是挖矿。这天卡斯丁狗背着一个最多能装重量为 n 的背包去矿洞里挖矿。从洞口看矿洞是一个深度为d等腰RT超级赛亚三角形,每个坐标点都有矿(如图)。洞口在三角形的最顶端,坐标为(1,1)。由于卡斯丁狗开挂,他只想从坐标为(x,y)的点走到坐标为(x+1,y)或者(x+1,y+1)的点,并且每经过一个点他可以选着挖或者不挖这个点的矿。问卡斯丁狗最多能背多少矿回家。



Input

第一行输入n,d。

接下来d行第i行输入i个数,表示矿的重量。

输入为小于300大于0。

Output

 输出最大能带走的矿。

Sample Input

100 3
99
1 99
100 1 44

Sample Output

100

【分析】

本质上还是01背包....其实一眼就可以看出来的,只是在01背包的基础上增加了一个移动路径,所以给人一种需要bfs搜索路径后dp的错觉....当然bfs也是没问题的。
但其实...不用考虑那么多三维dp直接做就可以了,因为数据不大只有300 ,  300*300*300*4/1024/1024≈102MB
所以直接干就行了...
f[i][j][k]表示到坐标(i,j)背包使用量为k时的最大价值,对于矿石,价格和体积都是a[i][j]
那么当前状态可以从f[i-1][j][k],f[i-1][j-1][k],f[i-1][j][k-a[i][j]],f[i-1][j-1][k-a[i][j]]四个状态移动过来
状态转移方程:f[i][j][k]=max(max(f[i-1][j][k],f[i-1][j-1][k]),max(f[i-1][j][k-a[i][j]]+a[i][j],f[i-1][j-1][k-a[i][j]]+a[i][j]));

显然方程虽然长,但是并没有什么特殊的地方... 就是一个三维的01背包...多了一个坐标限制条件罢了,因为限制了坐标,所以无所谓k正着还是反着~

(PS.这里我为了省内存所以没有读取a[i][j],因为a[i][j]的时效性只有一次,所以重复读取进一个变量也可以)
【代码】
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int f[310][310][310];

int main()
{
int n,m,x;
while (~scanf("%d%d",&m,&n))
{
memset(f,0,sizeof(f));
int ans=0;
//for (int i=1;i<=n;i++) for (int j=1;j<=i;j++) scanf("%d",&a[i][j]);
for (int i=1;i<=n;i++)
for (int j=1;j<=i;j++)
{
scanf("%d",&x);
for (int k=x;k<=m;k++)
{
f[i][j][k]=max(max(f[i-1][j][k],f[i-1][j-1][k]),max(f[i-1][j][k-x]+x,f[i-1][j-1][k-x]+x));
ans=max(ans,f[i][j][k]);
}
}
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: