The Test of Girlfriend

Title Description

At last, it's winter vacation. Xiaoming is going to the movies with his girlfriend. This day, her girlfriend wanted to give Xiao Ming a test. While Xiao Ming was preparing to leave, her girlfriend told him that she was waiting for him in the cinema. Xiao Ming's route to come must meet the given rules:
1. Assuming that Xiao Ming is at point 1 and his girlfriend is at point n, there are n-2 points between them. Xiao Ming can only go to a larger position than the current point number when he leaves.
2. Xiao Ming can't go through some places in a certain order when he comes. For example, if a girlfriend tells Xiao Ming that he can't go through 1-> 2-> 3, then the path that Xiao Ming should take when he comes can't include 1-> 2-> 3, but 1-> 3 or 1-> 2 are all possible. There may be many restrictive paths.  
This makes Xiao Ming very headache, and now he has left the problem to you.  
In particular, if the three points of 123 are collinear, but Xiao Ming continues directly from 1 to 3 and then from 3, then this situation does not consider Xiao Ming passing through this point.  
Now, Xiao Ming wants to go the shortest way to meet his girlfriend as soon as possible, but he doesn't want to break the rules of his girlfriend. Can you help Xiao Ming solve this problem?

Input Description:

The input contains many groups of samples, each group of samples contains two integers n and m at first. Among them, n represents n points, Xiao Ming is at point 1, girlfriend is at point n, and M represents Xiao Ming's girlfriend has m requirements.
       
Next, in line n, enter two integers x and Y (both X and y are in the int range), representing the location of the n points (the number of the points is from 1 to n).
       
Then there are m requests, each requesting two lines. First, one line is a k, which indicates that the request is related to K points, and then the K point numbers given in sequence, which means Xiao Ming can't walk k1-> k2-> k3... -> The path of Ki in this order;
       
When n and m are equal to 0, the input ends.
       

  
       [Technical Specification]
  2 <= n <= 50 
  1 <= m <= 100 
  2 <= k <= 5 

Output description:

For each sample, if there is a shortest path that meets the requirement, output the shortest path, leaving two decimal digits; otherwise, output "Can not be reached!" (quotation marks do not need to be output).
Example 1

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

output

2.00
Can not be reached!
21.65
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const double INF = 1e20;
int n;
 
pair<int,int> p[100];
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));
}
double dp[55][1000];
void CheckMin(double &a,double b)
{
    a = min(a,b);
}
struct Trie
{
    int next[1000][55],fail[1000],end[1000];
    int root,L;
    int newnode()
    {
        for(int i = 1; i <= n;i++)
            next[L][i] = -1;
        end[L++] = 0;
        return L-1;
    }
    void init()
    {
        L = 0;
        root = newnode();
    }
    void insert(int a[],int cnt)
    {
        int now = root;
        for(int i  = 0;i < cnt;i++)
        {
            if(next[now][a[i]] == -1)
                next[now][a[i]] = newnode();
            now = next[now][a[i]];
        }
        end[now] = 1;
    }
    void build()
    {
        queue<int>Q;
        fail[root] = root;
        for(int i = 1;i <= n;i++)
            if(next[root][i] == -1)
                next[root][i] = root;
            else
            {
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        while(!Q.empty())
        {
            int now = Q.front();
            Q.pop();
            end[now] |= end[fail[now]];
            for(int i = 1;i <= n;i++)
                if(next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else
                {
                    fail[next[now][i]] = next[fail[now]][i];
                    Q.push(next[now][i]);
                }
        }
 
    }
    void solve()
    {
        for(int i = 1;i <= n;i++)
            for(int j = 0;j < L;j++)
                dp[i][j] = INF;
        dp[1][next[root][1]] = 0;
        for(int i = 1;i < n;i++)
            for(int j = 0;j < L;j++)
                if(dp[i][j] < INF)
                {
                    for(int k = i+1;k <= n;k++)
                    {
                        int ss = next[j][k];
                        if(end[ss])continue;
                        CheckMin(dp[k][ss],dp[i][j] + dis(p[i],p[k]));
                    }
                }
        double ans = INF;
        for(int i = 0;i < L;i++)
            if(dp[n][i] < INF)
                CheckMin(ans,dp[n][i]);
        if(ans == INF)printf("Can not be reached!\n");
        else printf("%.2f\n",ans);
    }
}ac;
 
int a[10];
int main()
{
    int m;
    while(scanf("%d%d",&n,&m) == 2)
    {
        if(n == 0 && m == 0)break;
        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;
}


Posted by julzk on Sun, 19 May 2019 20:01:40 -0700