zoukankan      html  css  js  c++  java
  • HDU

    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
    思路:设dp[i][j]表示到第i个点,自己主动机状态到j的最小步数,注意的是由于我们是依据不合法的路径构造自己主动机的,所以我们是不能走到某一条路径的末尾的,依据这点来记录我们的终止条件

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <set>
    #include <queue>
    #include <cmath>
    using namespace std;
    const double inf = 1e20;
    
    pair<int, int> p[100];
    int n;
    double dp[55][1000];
    
    double dis(pair<int, int> a, pair<int, int> b) {
    	  return sqrt((double)(1.0 * a.first - b.first) * (1.0 * a.first - b.first) + (double)(1.0 * a.second - b.second)*(1.0 * a.second - b.second));
    }
    
    struct Tie {
    	int nxt[1000][55], fail[1000], end[1000];
    	int root, cnt;
    
    	int newNode() {
    		for (int i = 1; i <= n; i++) 
    			nxt[cnt][i] = -1;
    		end[cnt++] = 0;
    		return cnt - 1;
    	}
    
    	void init() {
    		cnt = 0;
    		root = newNode();
    	}
    
    	void insert(int a[], int len) {
    		int now = root;
    		for (int i = 0; i < len; i++) {
    			if (nxt[now][a[i]] == -1)
    				nxt[now][a[i]] = newNode();
    			now = nxt[now][a[i]];
    		}
    		end[now] = 1;
    	}
    
    	void build() {
    		queue<int> q;
    		fail[root] = root;
    		for (int i = 1; i <= n; i++) {
    			if (nxt[root][i] == -1)
    				nxt[root][i] = root;
    			else {
    				fail[nxt[root][i]] = root;
    				q.push(nxt[root][i]);
    			}
    		}
    
    		while (!q.empty()) {
    			int now = q.front();
    			q.pop();
    			end[now] |= end[fail[now]];
    			for (int i = 1; i <= n; i++) {
    				if (nxt[now][i] == -1)
    					nxt[now][i] = nxt[fail[now]][i];
    				else {
    					fail[nxt[now][i]] = nxt[fail[now]][i];
    					q.push(nxt[now][i]);
    				}
    			}
    		}
    	}
    
    	void solve() {
    		for (int i = 1; i <= n; i++)
    			for (int j = 0; j < cnt; j++)
    				dp[i][j] = inf;
    		dp[1][nxt[root][1]] = 0;
    		for (int i = 1; i < n; i++) 
    			for (int j = 0; j < cnt; j++) 
    				if (dp[i][j] < inf) {
    					for (int k = i+1; k <= n; k++) {
    						int cur = nxt[j][k];
    						if (end[cur]) continue;
    						dp[k][cur] = min(dp[k][cur], dp[i][j] + dis(p[i], p[k]));
    					}
    				}
    
    		double ans = inf;
    		for (int i = 0; i < cnt; i++) 
    			if (dp[n][i] < inf) 
    				ans = min(ans, dp[n][i]);
    
    		if (ans == inf) 
    			printf("Can not be reached!
    ");
    		else printf("%.2lf
    ", ans);
    	}
    } ac;
    
    int a[10];
    
    int main() {
    	int m;
    	while (scanf("%d%d", &n, &m) != EOF && n + m) {
    		for (int i = 1; i <= n; i++) 
    			scanf("%d%d", &p[i].first, &p[i].second);
    		ac.init();
    
    		int k;
    		while (m--) {
    			scanf("%d", &k);
    			for (int i = 0; i < k; i++)
    				scanf("%d", &a[i]);
    			ac.insert(a, k);
    		}
    
    		ac.build();
    		ac.solve();
    	}
    	return 0;
    }




  • 相关阅读:
    Java面向对象编程之异常处理机制
    LinkedList链式集合
    Java之反射机制
    适配器模式
    QuickHit
    Java之单例模式
    Java面向对象之接口
    多线程
    线程同步
    试题分析
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7372145.html
Copyright © 2011-2022 走看看