hdu 4435 第37届ACM/ICPC天津现场赛E题

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

题目:给出N个城市,从1开始需要遍历所有点,选择一些点建立加油站,使得花费最少

这题的特殊性在于他的花费上,2^(i-1)

利用一个非常重要的性质,2^0+2^1+2^2……+2^i<2^(i+1)

所有编号<=i的所有点都建,总花费比建一个还少。

这里就贪心一下,先假设所有点都建,然后依次从编号大的删点,看看能不能遍历整个图

dist[i]表示点i距离最近的一个加油站的距离

分析:突破口在于在i号点建立加油站的费用为2^i,这样特殊的花费会使得我们有一个贪心的规律,就是尽量不在号比较大的点建加油站,如果在n号点 建立加油站的费用会大于在除n以外的所有点都建加油站的总费用。所以我们可以先尝试把除n以外的所有点建立加油站,观察是否满足要求。若满足则说明我们必 然不会在n点建立加油站,若不满足我们就一定要在n点建加油站。若需要建,我们就建,然后就不用再考虑n点了,在确定了n点之后,我们用同样的方法来观察 n-1号点是否需要建立加油站,即将1~n-2号点都建立加油站,观察是否满足要求。以此类推,可以推出所有点的情况。

接下来我们需要解决对于一种给定的加油站建立情况,我们如何判断它是否满足题中的travel around的要求。分为两部判断,1.判断所有加油站是否可达(从1号点开始广搜,若到当前点距离<=d则入队)。2.判断其余点是否可达(刚才 的广搜过程可以顺便标出每个点到最近的加油站的距离,要求能从加油站到该点并返回加油站,所以点到加油站的距离必须小于等于d/2)。若满足这两点必然符 合要求,否则不符合要求。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<map>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<vector>
  7 #include<algorithm>
  8 #include<set>
  9 #include<string>
 10 #include<queue>
 11 #define inf 1<<30
 12 #define M 2005
 13 #define N 130
 14 #define maxn 300005
 15 #define eps 1e-10
 16 #define zero(a) fabs(a)<eps
 17 #define Min(a,b) ((a)<(b)?(a):(b))
 18 #define Max(a,b) ((a)>(b)?(a):(b))
 19 #define pb(a) push_back(a)
 20 #define mp(a,b) make_pair(a,b)
 21 #define mem(a,b) memset(a,b,sizeof(a))
 22 #define LL long long
 23 #define lson step<<1
 24 #define rson step<<1|1
 25 #define MOD 1000000009
 26 #define sqr(a) ((a)*(a))
 27 #define Key_value ch[ch[root][1]][0]
 28 #pragma comment(linker, "/STACK:1024000000,1024000000")
 29 using namespace std;
 30 struct Point
 31 {
 32     int x,y;
 33 }p[N];
 34 int n,d;
 35 int path[N][N];
 36 int ok[N];
 37 double dist(int i,int j)
 38 {
 39     return sqrt((double)sqr(p[i].x-p[j].x)+sqr(p[i].y-p[j].y));
 40 }
 41 bool bfs()
 42 {
 43     bool vis[N];
 44     int dist[N];
 45     queue<int>que;
 46     mem(vis,false);
 47     for(int i=0;i<n;i++)
 48     {
 49         //本身是加油站,距离是0
 50         if(ok[i]) dist[i]=0;
 51         else dist[i]=inf;
 52     }
 53     que.push(0);vis[0]=true;
 54     while(!que.empty())
 55     {
 56         int u=que.front();
 57         que.pop();
 58         for(int i=0;i<n;i++)
 59         {
 60             if(!vis[i]&&path[u][i]<=d)
 61             {
 62                 dist[i]=min(dist[i],dist[u]+path[u][i]);
 63                 if(ok[i])
 64                 {
 65                     que.push(i);
 66                     vis[i]=true;
 67                 }
 68             }
 69         }
 70     }
 71     for(int i=0;i<n;i++)
 72     {
 73         //虽然本身是个加油站,但是从1出发根本到不了
 74         if(ok[i]&&!vis[i]) return false;
 75         //不是一个加油站,不能保证从一个有加油站的地方来回
 76         if(!ok[i]&&dist[i]*2>d) return false;
 77     }
 78     return true;
 79 }
 80 void slove()
 81 {
 82     for(int i=0;i<n;i++) ok[i]=1;
 83     if(!bfs()) {puts("-1");return ;}  //全部都建还不能遍历
 84     for(int i=n-1;i>0;i--)
 85     {
 86         ok[i]=0;
 87         if(!bfs()) ok[i]=1;
 88     }
 89     int j=n-1;
 90     while(!ok[j]) j--;
 91     for(int i=j;i>=0;i--) printf("%d",ok[i]);
 92     puts("");
 93 }
 94 int main()
 95 {
 96     while(scanf("%d%d",&n,&d)!=EOF)
 97     {
 98         for(int i=0;i<n;i++) scanf("%d%d",&p[i].x,&p[i].y);
 99         for(int i=0;i<n;i++)
100         {
101             for(int j=0;j<n;j++)
102             {
103                 path[i][j]=ceil(dist(i,j));
104             }
105         }
106         slove();
107     }
108     return 0;
109 }
时间: 2024-12-25 22:39:52

hdu 4435 第37届ACM/ICPC天津现场赛E题的相关文章

hdu 4432 第37届ACM/ICPC天津现场赛B题

题目大意就是找出n的约数,然后把约数在m进制下展开,各个数位的每一位平方求和,然后按m进制输出. 模拟即可 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9

hdu 4431 第37届ACM/ICPC 天津赛区现场赛A题 枚举

题意:就是给了13张牌.问增加哪些牌可以胡牌.m是数字,s是条,p是筒,c是数字 胡牌有以下几种情况: 1.一个对子 +  4组 3个相同的牌或者顺子.  只有m.s.p是可以构成顺子的.东西南北这样的牌没有顺子. 2.7个不同的对子. 3.1m,9m,1p,9p,1s,9s,1c,2c,3c,4c,5c,6c,7c.  这13种牌每种都有,而且仅有这13种牌.肯定是有一种2张.其他的1张. 模拟即可,第一个对子的情况需要枚举 很麻烦的模拟,但是貌似稳银的很需要这题,所以这种难度必须要弄懂,加油

hdu 4438 第37届ACM/ICPC 天津赛区现场赛H题

题意:Alice和Bob两个人去打猎,有两种(只)猎物老虎和狼: 杀死老虎得分x,狼得分y: 如果两个人都选择同样的猎物,则Alice得分的概率是p,则Bob得分的概率是(1-p): 但是Alice事先知道Bob先选老虎的概率是Q,问Alice得分的期望最大值是 求期望 如果先去打老虎,则会有bob先去打狼和bob去打老虎两种情况,期望相加则是alice去打老虎的期望,然后求打狼的期望,比较大小即可 1 #include<cstdio> 2 #include<iostream> 3

2013 ACM/ICPC 长沙现场赛 A题 - Alice&#39;s Print Service (ZOJ 3726)

Alice's Print Service Time Limit: 2 Seconds      Memory Limit: 65536 KB Alice is providing print service, while the pricing doesn't seem to be reasonable, so people using her print service found some tricks to save money. For example, the price when

hdu 4462 第37届ACM/ICPC 杭州赛区 J题

题意:有一块n*n的田,田上有一些点可以放置稻草人,再给出一些稻草人,每个稻草人有其覆盖的距离ri,距离为曼哈顿距离,求要覆盖到所有的格子最少需要放置几个稻草人 由于稻草人数量很少,所以状态压缩枚举,之后慢慢判断即可,注意放稻草人的格子是不需要覆盖的 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath>

hdu 4461 第37届ACM/ICPC杭州赛区I题

题意:给两个人一些棋子,每个棋子有其对应的power,若b没有或者c没有,或者二者都没有,那么他的total power就会减1,total power最少是1,求最后谁能赢 如果b或c出现的话,flag就标记为1,那么在判断的时候如果flag==0,就说明他们没出现过,那么就要-1,然后就wa了,必须要两个变量判断,不知道为什么 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #inclu

hdu 4463 第37届ACM/ICPC杭州赛区K题 最小生成树

题意:给坐标系上的一些点,其中有两个点已经连了一条边,求最小生成树的值 将已连接的两点权值置为0,这样一定能加入最小生成树里 最后的结果加上这两点的距离即为所求 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map>

2013 ACM/ICPC 长沙现场赛 C题 - Collision (ZOJ 3728)

Collision Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge There's a round medal fixed on an ideal smooth table, Fancy is trying to throw some coins and make them slip towards the medal to collide. There's also a round range which

zoj 3659 第37届ACM/ICPC 长春赛区现场赛E题 (并查集)

题意:给出一棵树,找出一个点,求出所有点到这个点的权值和最大,权值为路径上所有边权的最小值. 用神奇的并查集,把路按照权值从大到小排序,然后用类似Kruskal的方法不断的加入边. 对于要加入的一条路,这条路连接这城市x和y,x所在的集合为A, y所在的集合为B, 可以确定A,B集合内的所有路都比当前这条路的权值大.如果让集合B加入集合A,就是让中心城市位于集合A,那么可以确定这两个集合合并之后的总权值为: A的权值总和+B的数量*当前这条路的权值.同样算出让集合B加入集合A的情况,取两者合并后