nyoj-307 宝物【dp+贪心】

原创 2015年07月09日 09:42:28

宝物

时间限制:1000 ms  |  内存限制:65535 KB
难度:6
描述

传说HMH大沙漠中有一个迷宫,里面藏有许多宝物。迷宫里可能有N个藏宝地点,用1到N标记。藏宝地点之间最多有一条通路相连。标记1为迷宫的进出口。

某天,Dr.Kong找到了迷宫的地图,他已经知道其中K(1<=K<=N)个不同的地点真的藏有宝物。Dr.Kong决定让他的机器人卡多去探险。卡多在经过某个藏宝地点时可能会拿走宝物。但它每拿走一个藏宝地点的宝物后,它的载重量就会增加W。迷宫中的通路不是平坦的,到处都是陷阱。假设每条通路都有一个危险度,其值与通过此路的载重量成正比。

机器人卡多进入迷宫时,它的载重量为0。只有当卡多携带宝物的载重量不大于某个通路的危险度时,它才能顺利通过此条道路,否则就会掉入陷阱,不能出来。

Dr.Kong希望他的机器人卡多尽量多的带出宝物,当然他更希望卡多最后能从标记1的地点走出去。

请你编写程序,帮助Dr.Kong计算一下,卡多最多能带出多少个藏宝地点的宝物。

输入
有多组测试数据,以EOF为输入结束的标志
第1行: N M K W
接下来有K行, 每行一个整数,表示藏有宝物的地点标号。
再接下来有M行,每行三个整数X,Y,Z,表示地点X与地点Y之间有一条危险度为Z的通路。
1 ≤ N ≤ 8000 1 ≤ K ≤ N 1 ≤ M ≤ 15000 1 ≤ W, Z ≤ 10000
数据保证所有的地点之间都是有道路可以到达的。
提示:机器人卡多经过一个藏宝地点时可以不拿走宝物, 而且同一个藏宝地点可以经过多次。
输出
输出有一个整数, 表示卡多最多能带出的宝物的堆数。
样例输入
6 7 5 1
1
2
3
4
5
1 2 3
3 6 2
6 2 10
2 4 1
5 1 1
4 5 1
1 6 1
样例输出
4

我最开始想的是用搜索解决,但是数据量太逼大了。所以果断放弃。

分析题目:

(1)每个藏有宝藏的节点你要保证拿了之后能回到1节点。

(2)尽快能的多拿


所以我想用动态规划来处理得到:每个节点到1节点路径的危险度限制最大是多少。

限制是由路径中最小的那条边来表示。maxPass[u]实质就是记录从1->u权值最小的边。对于maxPass[v]就只记录限制最大的情况。

所以的状态转移方程:maxPass[v]=findMax(maxPass[v],findMin(maxPass[u],z)); 写起来很像spfa额。。。。Orz


接下来就是进行排序,用贪心的思想去多多的拿取。还是在代码中理解吧。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
#define Max_V 8100
#define inf 0x3f3f3f3f
using namespace std;
int n,m,k,w;
struct Edge{
	int x,y,z;
};
vector<Edge> g;
bool have[Max_V];//标记该节点是否有宝藏
int maxPass[Max_V];//<span style="font-size: 13.3333339691162px;">每个节点到1节点路径的危险度限制最大是多少</span>
int ik[Max_V];//有效的宝藏点
int p[Max_V];//贪心用的数组
int findMax(int a,int b)
{
	return a>b?a:b;
}
int findMin(int a,int b)
{
	return a>b?b:a;
}
void init()
{
	g.clear();
	memset(have,0,sizeof(have));
}
void add_edge(int x,int y,int z)
{//无向图
	g.push_back((Edge){x,y,z});
	g.push_back((Edge){y,x,z});
}
int cmp(const void *a,const void *b)
{
	return *(int *)a-*(int *)b;
}
int find_way()
{//动态规划找到每个节点到1节点<span style="font-size: 13.3333339691162px;">路径的危险度限制最大是多少</span>
	memset(maxPass,0,sizeof(maxPass));
	maxPass[1]=inf;
	bool flag=true;
	int u,v,z;
	while(flag)
	{
		flag=false;//当遍历所有边都没有maxPass数组更新时,说明动规结束
		for(int i=0;i<g.size();i++)
		{
			u=g[i].x;v=g[i].y;z=g[i].z;
			int t=maxPass[v];
			maxPass[v]=findMax(maxPass[v],findMin(maxPass[u],z));
			if (maxPass[v]!=t)//如果有一个节点的maxPass数组有更新,那么这个节点就可能去更新其它节点。所以动规不终止
				flag=true;
		}
	}
	int count=0;
	for(int j=1;j<=n;j++)
		if(have[j]&&maxPass[j]>=w)//将藏有宝藏的节点记录
			ik[count++]=maxPass[j];
	return count;
}
int solve()
{
	int mk=find_way();
	p[0]=1;
	qsort(ik,mk,sizeof(int),cmp);//排序后贪心
	for(int i=1;i<mk;i++)
	{
		if(ik[i]>=p[i-1]*w+w)
			p[i]=p[i-1]+1;
		else p[i]=p[i-1];
	}
	return p[mk-1];
}
int main()
{
	int i;
	while(~scanf("%d%d%d%d",&n,&m,&k,&w))
	{
		init();
		int loc;
		for(i=0;i<k;i++)
		{
			scanf("%d",&loc);
			have[loc]=1;
		}
		int x,y,z;
		for(i=0;i<m;i++)
		{
			scanf("%d%d%d",&x,&y,&z);
			add_edge(x,y,z);
		}
		printf("%d\n",solve());
	}
	return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

zoj3541(区间dp+贪心)

链接:点击打开链接 题意:给出一排按钮,要求把所有按钮全部按下,每移动一单位距离需要一单位时间,给出每个按钮的位置,并且每个按钮按下后经过一定的时间又会弹起来,把所有按钮按下的步骤 代码: #incl...
  • stay_accept
  • stay_accept
  • 2016年05月28日 19:06
  • 448

摇钱树 dp+贪心

摇钱树 Time Limit: 1000MS   Memory Limit: 1000K Total Submissions: 106   Accepted: 33...
  • black_miracle
  • black_miracle
  • 2017年02月23日 17:16
  • 117

线段覆盖系列(dp+贪心)

我的内心毫无波动......
  • Blue_CuSO4
  • Blue_CuSO4
  • 2017年05月10日 19:21
  • 128

la 4731 贪心+DP+概率

其实不要概率知识……题目给了公式 开始其实就想到,大的应该放前面,不过还有如何划分等各个问题,所以没有敢直接下手证明 分析了对于某一种划分方式,应该把那个组放在最前面(可证明 (∑P)/个数)最大...
  • qq_21704477
  • qq_21704477
  • 2016年04月07日 21:42
  • 341

DP斜率优化总结

DP斜率优化总结 寒假事情比较多,刚回来的一周都是聚会,外加自己不务正业了几天浪费了大半的时间,春节前后还是抽空学习了一下斜率优化DP。 理论基础见NOI2004年周源的论...
  • pi9nc
  • pi9nc
  • 2013年07月27日 21:45
  • 7593

吉首大学新生赛 Jack的宝物问题 (前缀和应用)

今天做新生赛,发现自己还是个菜狗.题目描述 Jack是个吃鸡玩家,一个偶然的机会Jack来到了神秘的P城,Jack发现P城有 N 种宝物,每种宝物有 x[i] 个。但是当Jack想把他们全部拿走时...
  • AC_jie
  • AC_jie
  • 2017年12月24日 17:31
  • 57

树形DP+贪心(乱搞)(HDU4714)

题意:给出一个树形图,要求把
  • u012859437
  • u012859437
  • 2014年11月10日 17:24
  • 661

NYOJ 贪心算法题目汇总(一)

题目6 题目信息 运行结果 本题排行 讨论区 喷水装置(一) 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述现有一块草坪,长为20米,宽为2米,要在横...
  • LiuJiuXiaoShiTou
  • LiuJiuXiaoShiTou
  • 2017年04月08日 19:25
  • 1130

贪心算法--看电视

竞技场测试中 可以使用acmclub各校账号登录 问题 F: 看电视 时间限制: 1 Sec 内存限制: 32 MB 提交: 233 解决: 111 提交...
  • qq_24722301
  • qq_24722301
  • 2015年04月04日 15:55
  • 888

贪心算法思想及实现

【算法思想】 贪心策略是指从问题的初始状态出发,通过若干次的贪心选择而得出最优值(或较优解)的一种解题方法。   其实,从"贪心策略"一词我们便可以看出,贪心策略总是做出在当前看来是最优的选择,也...
  • zhenyu5211314
  • zhenyu5211314
  • 2014年01月20日 12:31
  • 1998
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:nyoj-307 宝物【dp+贪心】
举报原因:
原因补充:

(最多只允许输入30个字)