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)。若满足这两点必然符 合要求,否则不符合要求。

 

2015-05-18:这里的dist维护的是到最近加油站的距离,要是最少肯定所有加油站都要路过

 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 #define MOD 1000000007

10 const int INF=0x3f3f3f3f;

11 const double eps=1e-5;

12 typedef long long ll;

13 #define cl(a) memset(a,0,sizeof(a))

14 #define ts printf("*****\n");

15 const int MAXN=130;

16 int n,m,tt;

17 int c[MAXN][MAXN],ok[MAXN],vis[MAXN],dist[MAXN],d;

18 struct Node

19 {

20     int x,y;

21     void in()

22     {

23         scanf("%d%d",&x,&y);

24     }

25 }node[MAXN];

26 bool bfs()

27 {

28     queue<int> q;

29     cl(vis);

30     for(int i=0;i<n;i++)

31     {

32         if(ok[i])   dist[i]=0;

33         else dist[i]=INF;

34     }

35     int now;

36     q.push(0);

37     vis[0]=1;

38     while(!q.empty())

39     {

40         now=q.front();

41         q.pop();

42         for(int i=0;i<n;i++)

43         {

44             if(!vis[i]&&c[now][i]<=d)

45             {

46                 dist[i]=min(dist[i],dist[now]+c[now][i]);

47                 if(ok[i])

48                 {

49                     q.push(i);

50                     vis[i]=1;

51                 }

52             }

53         }

54     }

55     for(int i=0;i<n;i++)

56     {

57         if(ok[i]&&!vis[i])  return 0;

58         if(!ok[i]&&dist[i]*2>d) return 0;

59     }

60     return 1;

61 }

62 int main()

63 {

64     int i,j,k;

65     #ifndef ONLINE_JUDGE

66     freopen("1.in","r",stdin);

67     #endif

68     while(scanf("%d%d",&n,&d)!=EOF)

69     {

70         for(i=0;i<n;i++)

71         {

72             node[i].in();

73         }

74         for(i=0;i<n;i++)

75         {

76             for(j=0;j<n;j++)

77             {

78                 c[i][j]=ceil(sqrt((double)(node[i].x-node[j].x)*(node[i].x-node[j].x)+(node[i].y-node[j].y)*(node[i].y-node[j].y)));

79             }

80         }

81         for(i=0;i<n;i++)    ok[i]=1;

82         if(!bfs())

83         {

84             puts("-1");

85             continue;

86         }

87         for(i=n-1;i>0;i--)

88         {

89             ok[i]=0;

90             if(!bfs())  ok[i]=1;

91         }

92         j=n-1;

93         while(!ok[j])      j--;

94         for(i=j;i>=0;i--)   printf("%d",ok[i]);

95         puts("");

96     }

97 }

 

你可能感兴趣的:(ICPC)