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;
}

  

posted @ 2015-03-20 17:13  chenjunjie1994  阅读(257)  评论(0编辑  收藏  举报