http://acm.hdu.edu.cn/showproblem.php?pid=4435
有题意可以知道 对应第k个城市 即使前(k-1)个城市都建立加油站 也没有在第k个城市建立加油站花的钱多
思路 :
如果全部都建立加油站 还是不能满足条件的话 则说明没有解决方案
否则 从后面逐个向前尝试看是否可以不建立
对于 是否能达到目的 我用的方法比较麻烦
两次 spfa 分别求到某个城市时 还未在此站加油(也可能没有加油站)最多可以有多少油 和 在某个城市想回来的话最少需要的油量
每个点必须满足 有的油量可以回来
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<set> #include<queue> #include<stack> #include<map> #include<string> #include<iomanip> using namespace std; #define LL long long const int INF=0x5fffffff; const double FINF=1e9; const int N=205; int d[N][N]; int x[N]; int y[N]; int dist[N]; int need[N]; int had[N]; bool in[N]; void spfa1(int s,int n,int k) { queue<int>qt; memset(in,false,sizeof(in)); for(int i=1;i<=n;++i) dist[i]=-1; dist[s]=0; in[s]=true; qt.push(s); while(!qt.empty()) { int x=qt.front(); qt.pop(); in[x]=false; for(int i=1;i<=n;++i) { if(i==s||i==x||d[x][i]>min(dist[x]+had[x],k)) continue; int tmp=min(dist[x]+had[x],k)-d[x][i]; if(dist[i]<tmp) { dist[i]=tmp; if(!in[i]) { in[i]=true; qt.push(i); } } } } } void spfa2(int s,int n,int k) { queue<int>qt; memset(in,false,sizeof(in)); for(int i=1;i<=n;++i) need[i]=INF; need[s]=0; in[s]=true; qt.push(s); while(!qt.empty()) { int x=qt.front(); qt.pop(); in[x]=false; for(int i=1;i<=n;++i) { if(d[x][i]+need[x]>k) continue; int tmp=need[x]+d[x][i]; tmp=tmp-had[i]; if(tmp<0) tmp=0; if(need[i]>tmp) { need[i]=tmp; if(!in[i]) { in[i]=true; qt.push(i); } } } } } bool Can(int n,int k) { spfa1(1,n,k); spfa2(1,n,k); for(int i=1;i<=n;++i) { if(need[i]>dist[i]) return false; } return true; } int main() { //freopen("data.txt","r",stdin); int n,k; while(scanf("%d %d",&n,&k)!=EOF) { for(int i=1;i<=n;++i) { scanf("%d %d",&x[i],&y[i]); for(int j=1;j<i;++j) { d[i][j]=d[j][i]=ceil(sqrt(1.0*(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))); } } for(int i=1;i<=n;++i) had[i]=k; if(!Can(n,k)) {printf("-1\n");continue;} int ans[N]; memset(ans,0,sizeof(ans)); ans[1]=1; for(int i=n;i>1;--i) { had[i]=0; if(!Can(n,k)) {had[i]=k;ans[i]=1;} } int i=n; while(!ans[i]) --i; for(int l=i;l>=1;--l) printf("%d",ans[l]); printf("\n"); } return 0; }