zoukankan      html  css  js  c++  java
  • HDU 4511 小明系列故事——女友的考验 (AC自动机 + DP)

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

    Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
    Total Submission(s): 2024    Accepted Submission(s): 556


    Problem Description
      终于放寒假了,小明要和女朋友一起去看电影。这天,女朋友想给小明一个考验,在小明正准备出发的时候,女朋友告诉他,她在电影院等他,小明过来的路线必须满足给定的规则:
      1、假设小明在的位置是1号点,女朋友在的位置是n号点,则他们之间有n-2个点可以走,小明每次走的时候只能走到比当前所在点编号大的位置;
      2、小明来的时候不能按一定的顺序经过某些地方。比如,如果女朋友告诉小明不能经过1 -> 2 -> 3,那么就要求小明来的时候走过的路径不能包含有1 -> 2 -> 3这部分,但是1 -> 3 或者1 -> 2都是可以的,这样的限制路径可能有多条。
      这让小明非常头痛,现在他把问题交给了你。
      特别说明,如果1 2 3这三个点共线,但是小明是直接从1到3然后再从3继续,那么此种情况是不认为小明经过了2这个点的。
      现在,小明即想走最短的路尽快见到女朋友,又不想打破女朋友的规定,你能帮助小明解决这个问题吗?
     
    Input
      输入包含多组样例,每组样例首先包含两个整数n和m,其中n代表有n个点,小明在1号点,女朋友在n号点,m代表小明的女朋友有m个要求;
      接下来n行每行输入2个整数x 和y(x和y均在int范围),代表这n个点的位置(点的编号从1到n);
      再接着是m个要求,每个要求2行,首先一行是一个k,表示这个要求和k个点有关,然后是顺序给出的k个点编号,代表小明不能走k1 -> k2 -> k3 ……-> ki这个顺序的路径;
      n 和 m等于0的时候输入结束。

      [Technical Specification]
      2 <= n <= 50
      1 <= m <= 100
      2 <= k <= 5
     
    Output
      对于每个样例,如果存在满足要求的最短路径,请输出这个最短路径,结果保留两位小数;否则,请输出”Can not be reached!” (引号不用输出)。
     
    Sample Input
    3 1 1 1 2 1 3 1 2 1 2 2 1 0 0 1 1 2 1 2 5 3 0 0 5 3 1 2 1 22 5 21 3 1 2 3 2 4 5 2 1 5 0 0
     
    Sample Output
    2.00 Can not be reached! 21.65
     
    Source
     
    Recommend
    liuyiding
     
    Statistic | Submit | Discuss | Note

    析:先把不能走的路径建立在AC自动机上,然后DP,dp[i][j]  表示当前在 i 结点,并且在 j 状态,然后再枚举就好,在建立AC自动机时,把违法状态都标记,在转移的时候路过这些状态。

    代码如下:

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    #include <set>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <cctype>
    #include <cmath>
    #include <stack>
    #include <sstream>
    #include <list>
    #include <assert.h>
    #include <bitset>
    #define debug() puts("++++");
    #define gcd(a, b) __gcd(a, b)
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define fi first
    #define se second
    #define pb push_back
    #define sqr(x) ((x)*(x))
    #define ms(a,b) memset(a, b, sizeof a)
    //#define sz size()
    #define pu push_up
    #define pd push_down
    #define cl clear()
    #define all 1,n,1
    #define FOR(i,x,n)  for(int i = (x); i < (n); ++i)
    #define freopenr freopen("in.txt", "r", stdin)
    #define freopenw freopen("out.txt", "w", stdout)
    using namespace std;
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int, int> P;
    const int INF = 0x3f3f3f3f;
    const double inf = 1e20;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int maxn = 50 + 10;
    const int maxm = 1e5 + 10;
    const int mod = 50007;
    const int dr[] = {-1, 0, 1, 0};
    const int dc[] = {0, -1, 0, 1};
    const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
    int n, m;
    const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    inline bool is_in(int r, int c) {
      return r >= 0 && r < n && c >= 0 && c < m;
    }
    const int maxnode = 100 * 5 + 100;
    const int sigma = 55;
    P a[maxn];
    inline double dist(const P &lhs, const P &rhs){
      return sqrt(sqr(lhs.fi*1.0-rhs.fi*1.0) + sqr(lhs.se*1.0-rhs.se*1.0));
    }
    
    double dp[maxn][maxnode];
    
    struct Aho{
      int ch[maxnode][sigma], f[maxnode];
      int val[maxnode];
      int sz;
    
      void init(){ sz = 1;  ms(ch[0], 0); }
    
      void insert(int *a, int len){
        int u = 0;
        for(int i = 0; i < len; ++i){
          int c = a[i];
          if(!ch[u][c]){
            ms(ch[sz], 0);
            val[sz] = 0;
            ch[u][c] = sz++;
          }
          u = ch[u][c];
        }
        val[u] = 1;
      }
    
      void getFail(){
        queue<int> q;
        f[0] = 0;
        for(int c = 0; c < sigma; ++c){
          int u = ch[0][c];
          if(u){ f[u] = 0; q.push(u);  }
        }
        while(!q.empty()){
          int r = q.front();  q.pop();
          for(int c = 0; c < sigma; ++c){
            int u = ch[r][c];
            if(!u){ ch[r][c] = ch[f[r]][c];  continue; }
            q.push(u);
            int v = f[r];
            while(v && !ch[v][c])  v = f[v];
            f[u] = ch[v][c];
            val[u] |= val[f[u]];
          }
        }
      }
    
      double solve(){
        for(int i = 0; i <= n; ++i)
          for(int j = 0; j <= sz; ++j)
            dp[i][j] = inf + 10;
        dp[1][ch[0][1]] = 0;
        for(int i = 1; i < n; ++i)
          for(int j = 0; j < sz; ++j){
            if(dp[i][j] >= inf)  continue;
            for(int k = i+1; k <= n; ++k){
              int nxt = ch[j][k];
              if(val[nxt])  continue;
              dp[k][nxt] = min(dp[k][nxt], dp[i][j] + dist(a[i], a[k]));
            }
          }
        double ans = inf + 10;
        for(int i = 0; i < sz; ++i)
          ans = min(ans, dp[n][i]);
        return ans;
      }
    };
    Aho aho;
    
    int b[10];
    
    int main(){
      while(scanf("%d %d", &n, &m) == 2 && n+m){
        for(int i = 1; i <= n; ++i)  scanf("%d %d", &a[i].fi, &a[i].se);
        aho.init();
        for(int i = 0; i < m; ++i){
          int len;
          scanf("%d", &len);
          for(int j = 0; j < len; ++j)  scanf("%d", b+j);
          aho.insert(b, len);
        }
        aho.getFail();
        double ans = aho.solve();
        if(ans >= inf)  puts("Can not be reached!");
        else  printf("%.2f
    ", ans);
      }
      return 0;
    }
    

      

  • 相关阅读:
    移动开发 Native APP、Hybrid APP和Web APP介绍
    urllib与urllib2的学习总结(python2.7.X)
    fiddler及postman讲解
    接口测试基础
    UiAutomator2.0 和1.x 的区别
    adb shell am instrument 命令详解
    GT问题记录
    HDU 2492 Ping pong (树状数组)
    CF 567C Geometric Progression
    CF 545E Paths and Trees
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/7632962.html
Copyright © 2011-2022 走看看