HDU 4511 小明系列故事——女友的考验

其实就是求1到n的最短路,且不包含特定子串,可以利用ac自动机构建不可到达的状态我们可以设dp【i】【j】来表示到达i节点时候位于自动机j节点的花费

ACcode:

#include <bits/stdc++.h>
const double inf=1e20;
using namespace std;
typedef pair<double,double> D;
D data[55];
double dp[55][505];
int in[15],N,m;
struct Aho{
    struct state{
        int next[55];
        int fail,cnt;
    }s[505];
    int size;
    queue<int>q;
    void init(){
        while(q.size())q.pop();
        for(int i=0;i<505;++i){
            memset(s[i].next,-1,sizeof(s[i].next));
            s[i].cnt=s[i].fail=0;
        }
        size=1;
    }
    void insert(int n){
        int now=0;
        for(int i=0;i<n;++i){
            if(s[now].next[in[i]]==-1)
                s[now].next[in[i]]=size++;
            now=s[now].next[in[i]];
        }
        s[now].cnt=1;
    }
    double dis(D& a,D& b){
        return sqrt((a.first-b.first)*(a.first-b.first)+(a.second-b.second)*(a.second-b.second));
    }
    void build(){
        s[0].fail=0;
        for(int i=0;i<55;++i)
            if(s[0].next[i]==-1)
                s[0].next[i]=0;
            else {
                s[s[0].next[i]].fail=0;
                q.push(s[0].next[i]);
            }
        while(q.size()){
            int u=q.front();
            q.pop();
            for(int i=0;i<55;++i)
                if(s[u].next[i]==-1)
                    s[u].next[i]=s[s[u].fail].next[i];
            else {
                s[s[u].next[i]].fail=s[s[u].fail].next[i];
                s[u].cnt|=s[s[u].fail].cnt;
                q.push(s[u].next[i]);
            }
        }
        fill(&dp[0][0],&dp[54][54-1],inf);;
        dp[0][s[0].next[0]]=0;
        for(int i=0;i<N-1;++i)
            for(int j=0;j<size;++j){
                if(dp[i][j]==inf)continue;
                for(int k=i+1;k<N;++k){
                    if(s[s[j].next[k]].cnt)continue;
                    dp[k][s[j].next[k]]=min(dp[k][s[j].next[k]],dp[i][j]+dis(data[i],data[k]));
                }

            }
        double ans=inf;
        for(int i=0;i<size;++i)ans=min(ans,dp[N-1][i]);
        if(ans==inf)printf("Can not be reached!\n");
        else printf("%.2f\n",ans);
    }
}aho;
int main(){
    while(cin>>N>>m){
        if(N==0&&m==0)break;
        aho.init();
        for(int i=0;i<N;++i)scanf("%lf%lf",&data[i].first,&data[i].second);
        for(int i=0;i<m;++i){
            int k;
            scanf("%d",&k);
            for(int j=0;j<k;++j){
                scanf("%d",&in[j]);
                in[j]--;
            }
            aho.insert(k);
        }
        aho.build();
    }
    return 0;
}
/*
6 2
1 3
2 4
5 7
4 3
2 8
7 8
3
1 3 4
2
5 6
*/


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值