还是思维不够灵活,刚开始,只想到了那个O(n3)的算法,知道肯定不行,苦苦思索,实在想不出来,浏览了一下其他人的博客,刚扫一眼,突然想到了还是从最优解的最后的状态考虑,得到了O(n2)的算法,就是对于节点i,枚举,在他左边的与他举例小于l3的点,得到状态转移方程f[i]=min(f[j]+cost),ac之,然后看了浩神的博客,还可以用二分优化,想了想,确实可以,因为点到s起点的举例是单调非减的,对于同一段的肯定最左边的最优,二分得之
#include <iostream> #include <cstdio> #define LL __int64 #define min(a,b) ((a)<(b)?(a):(b)) using namespace std; const int maxn=10000+10; const int inf=0x3f3f3f3f; int l1,l2,l3,c1,c2,c3,n,s,e; int dis[maxn]; int f[maxn]; int search(int de,int cm,int cost) { int l=s,r=de,mid; while(r-l>0) { mid=l+(r-l)/2; if((dis[de]-dis[mid])<=cm) r=mid; else l=mid+1; } return f[r]+cost; } int main() { while(~scanf("%d%d%d%d%d%d",&l1,&l2,&l3,&c1,&c2,&c3)) { scanf("%d",&n); scanf("%d%d",&s,&e); int tem; if(s>e) { tem=s; s=e; e=tem; } int i,j; for(i=2;i<=n;i++) scanf("%d",&dis[i]); f[s]=0; for(i=s+1;i<=e;i++) { f[i]=inf; f[i]=min(f[i],search(i,l1,c1)); f[i]=min(f[i],search(i,l2,c2)); f[i]=min(f[i],search(i,l3,c3)); } printf("%d\n",f[e]); } return 0; }