#hdu 4435 charge-station#
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4435
利用二进制的特殊性,对于第i个城市cost为2i-1,也就是说即使0~i-1号城市都建立加油站,
花费也赶不上在i点建加油站,所以,思路:先每个城市建加油站,从高往低变了,能不建的就不建。
对于去掉后判断时候可行,不难,一遍dfs就行:
如果u点,v点都有加油站,dis( u, v ) <= d;
如果u点有加油站,v点无加油站,dis( u, v ) <= d/2;(保证可以回来)
不说了,简单题,代码:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<cmath> using namespace std; const int maxn = 200; int n; double d; struct Node{ double x, y; }node[maxn]; int vis[maxn], ans[maxn]; double dis( int i, int j ){ double x1 = node[i].x, y1 = node[i].y; double x2 = node[j].x, y2 = node[j].y; return ceil(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))); } void dfs( int u ){ for( int v = 1; v <= n; ++v ){ if( v == u || vis[v] == 1 ) continue; if( ans[v] == 1 && dis( u, v ) <= d ){ //v点存在加油站且可达 vis[v] = 1; dfs(v); }else if( ans[v] == 0 && dis( u, v ) <= d/2 ){ //v点无加油站但可达 vis[v] = 1; } } } bool judge( int u ){ ans[u] = 0; memset( vis, 0, sizeof(vis) ); vis[1] = 1; dfs(1); int flag = 1; for( int i = 1; i <= n; ++i ){ if(vis[i] == 0){ flag = 0; break; } } //回退 ans[u] = 1; return flag; } void solve(){ for( int i = n; i >= 2; --i ){ if(judge(i)) ans[i] = 0; } } void print(){ int e = n; for( int i = n; i >= 1; --i ){ if( ans[i] == 0 ) e--; else break; } for( int i = e; i >= 1; --i ){ printf("%d", ans[i]); } printf("\n"); } int main(){ //freopen("4438.in", "r", stdin); while(scanf("%d%lf", &n, &d) != EOF){ memset( node, 0, sizeof(node) ); for( int i = 1; i <= n; ++i ){ scanf("%lf%lf", &node[i].x, &node[i].y); } bool flag = 1; for( int i = 1; i <= n; ++i ){ ans[i] = 1; bool flag1 = 0; for( int j = 1; j <= n; ++j ){ if( i == j ) continue; if( dis( i, j ) <= d ) flag1 = 1; } if( flag1 == 0 ){ flag = 0; break; } } //存在某一节点不可达 if(!flag){ printf("-1\n"); continue; } solve(); print(); } return 0; }