HDU 4511
SHIT,SHIT,SHIT,SHIT,SHIT...
这道题可以使用AC自动机+DP来解决。也就是用非法路径建立TRIE图,然后从trie[root][1]点开始广搜DP即可。千万要注意一点,题目里有说:小明每次走的时候只能走到比当前所在点编号大的位置
因为这个WA了无限次。。。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #define LL __int64 using namespace std; const int N=25000; const int root=0; int trie[N][55]; int fail[N]; bool tag[N]; int que[N],head,tail,tot; int n,m; double dp[550][55],d[55][55]; struct Point{ double x,y; }point[55]; void init(){ for(int i=0;i<=549;i++){ for(int j=0;j<=50;j++) dp[i][j]=1e20; } head=tail=tot=0; memset(fail,-1,sizeof(fail)); memset(tag,false,sizeof(tag)); } double dist(int i,int j){ return sqrt((point[i].x-point[j].x)*(point[i].x-point[j].x)+(point[i].y-point[j].y)*(point[i].y-point[j].y)); } int sthead,stail; struct Stat{ int pos_in_trie,pos; Stat(){}; Stat(int a,int b){ pos_in_trie=a,pos=b; } }stque[N*10]; void clr(int p){ memset(trie[p],-1,sizeof(trie[p])); } void build_ac(){ head=tail=0; que[tail++]=root; while(head!=tail){ int tmp=que[head++]; int p=-1; for(int i=1;i<=n;i++){ if(trie[tmp][i]!=-1){ if(tmp==root) fail[trie[tmp][i]]=root; else{ p=fail[tmp]; while(p!=-1){ if(trie[p][i]!=-1){ fail[trie[tmp][i]]=trie[p][i]; break; } p=fail[p]; } if(p==-1) fail[trie[tmp][i]]=root; } if(tag[fail[trie[tmp][i]]]) tag[trie[tmp][i]]=tag[fail[trie[tmp][i]]]; que[tail++]=trie[tmp][i]; } else{ //trie[tmp][i]==-1 if(tmp==root) trie[tmp][i]=root; else{ p=fail[tmp]; while(p!=-1){ if(trie[p][i]!=-1){ trie[tmp][i]=trie[p][i]; break; } p=fail[p]; } if(p==-1) trie[tmp][i]=root; } } } } } void BFS(){ Stat tmp; while(sthead<stail){ tmp=stque[sthead++]; for(int i=tmp.pos;i<=n;i++){ if(!tag[trie[tmp.pos_in_trie][i]]){ if(dp[trie[tmp.pos_in_trie][i]][i]>dp[tmp.pos_in_trie][tmp.pos]+d[i][tmp.pos]){ dp[trie[tmp.pos_in_trie][i]][i]=dp[tmp.pos_in_trie][tmp.pos]+d[i][tmp.pos]; stque[stail++]=Stat(trie[tmp.pos_in_trie][i],i); } } } } } int main(){ int k; while(scanf("%d%d",&n,&m),n||m){ init(); for(int i=1;i<=n;i++) scanf("%lf%lf",&point[i].x,&point[i].y); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++) d[i][j]=dist(i,j); } int p,tmp; clr(0); for(int i=1;i<=m;i++){ scanf("%d",&k); p=0; for(int j=1;j<=k;j++){ scanf("%d",&tmp); if(trie[p][tmp]==-1){ clr(++tot); trie[p][tmp]=tot; } p=trie[p][tmp]; } tag[p]=true; } build_ac(); sthead=stail=0; dp[trie[root][1]][1]=0; stque[stail++]=Stat(trie[root][1],1); BFS(); double ans=1e20; for(int i=0;i<550;i++) ans=min(ans,dp[i][n]); if(ans==1e20) printf("Can not be reached!\n"); else printf("%.2lf\n",ans); } return 0; }