转载请注明出处,谢谢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("***** "); 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 }