看完题目第一遍,感觉很简单。当写完程序跑测试用例的时候,发现第二个总是过不了,然后好好研究了一下测试用例,才知道原来不是程序有问题,而是我的建图方式错了。对于这些无序的点,如果高的在右边,不等式是dis[tall]-dis[short]<=d;如果高的在左边,那么不等式就要变成dis[short]-dis[tall]<=d了。
另一个条件就是1<= dis[i+1]-dis[i] <=d;
一定要选最高的和最低的两个点其中最靠左边的作为源点,那么求一次最短路的意义就是另一个点到它的最远距离。
看代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define Maxn 1010 #define inf 0x7fffffff #define Maxm Maxn*Maxn using namespace std; int dis[Maxn],index[Maxn],vi[Maxn],e,n; struct Edge{ int to,next,val,from; }edge[Maxm]; struct Point{ int num,val; }p[Maxn]; void init() { memset(vi,0,sizeof(vi)); memset(index,-1,sizeof(index)); e=0; for(int i=0;i<=n;i++) { dis[i]=inf; } } void addedge(int from, int to ,int val) { edge[e].to=to; edge[e].from=from; edge[e].val=val; edge[e].next=index[from]; index[from]=e++; } int bellman_ford(int u) { int i,j,temp,flag; dis[u]=0; for(i=1;i<=n;i++) { flag=1; for(j=0;j<e;j++) { temp=edge[j].from; if(dis[temp]<inf&&dis[temp]+edge[j].val<dis[edge[j].to]) { dis[edge[j].to]=dis[temp]+edge[j].val; flag=0; } } if(flag) return 1; } return 0; } int cmp(Point a,Point b) { return a.val<b.val; } int main() { int i,j,t,d,Case=0; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&d); init(); for(i=1;i<=n;i++) { scanf("%d",&p[i].val); p[i].num=i; } for(i=1;i<n;i++) { addedge(i+1,i,-1); addedge(i,i+1,d); } sort(p+1,p+n+1,cmp); for(i=1;i<n;i++) { if(p[i].num>p[i+1].num) { addedge(p[i+1].num,p[i].num,d); addedge(p[i].num,p[i+1].num,-1); } else { addedge(p[i].num,p[i+1].num,d); addedge(p[i+1].num,p[i].num,-1); } } int u; if(p[1].num>p[n].num) u=p[n].num; else u=p[1].num; if(bellman_ford(u)) printf("Case %d: %d ",++Case,abs(dis[p[n].num]-dis[p[1].num])); else printf("Case %d: -1 ",++Case); //for(i=1;i<=n;i++) //cout<<dis[i]<<" "; //cout<<endl; } return 0; }