用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字
云代码 - c代码库

2013腾讯马拉松初赛 ACM 小明系列故事——女友的考验

2013-03-25 作者: 小蜜锋举报

[c]代码库

/*

2013腾讯马拉松初赛第2场

1002 小明系列故事——女友的考验
 
Time Limit: 0.2 Seconds   Memory Limit: 32768K
 
终于放寒假了,小明要和女朋友一起去看电影。这天,女朋友想给小明一个考验,在小明正准备出发的时候,女朋友告诉他,她在电影院等他,小明过来的路线必须满足给定的规则:
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
*/



/*
解题报告:

这题初看没什么头续,看到了这些路径,然后又想看的数据范围,K很好,想到了Trie,然后又想到了字符串匹配,于是想到了AC自动机。
想到了AC自动机,这题就好做了,就是一个AC自动机DP嘛。

把题目给的非法路径构成一棵Trie树,然做跑一次AC自动机。
然后做DP
dp[i][j]代表在第i个点自动机状态在j的最小距离。
然后枚举可走的点去转移就行了。
自动机状态最多有5*100个。
总的DP状态有50*500,每一个转移是50,最后的复杂度是50*50*500
*/

#include<stdio.h>
#include<math.h>
#include<string.h>
const int MAX = 1005;
const int MAXSON = 50;
struct {
    int id, next[MAXSON], fail;
} node[1000000];

int n, tot;
char mod[1000005];
int len[MAX];
int q[1000000];
void clr() {
    int i;
    tot++;
    for(i = 0; i < MAXSON; i++)
        node[tot].next[i] = 0;
    node[tot].id = node[tot].fail = 0;
}
void ins() {
    int tmp, i, n;
    int h = 0;
    scanf("%d", &n);
    while(n--) {
        scanf("%d", &tmp);
        tmp--;
        if(node[h].next[tmp] == 0) {
            clr();
            node[h].next[tmp] = tot;
        }
        h = node[h].next[tmp];
    }
    node[h].id++;
}
void get_fail() {
    int h = 0, i;
    int f = -1, r = 0;
    int tmp, fail, k;
    q[0] = 0;
    while(f != r) {
        tmp = q[++f];
        if(node[node[tmp].fail].id > 0) //自动机添加一个往前走的东西。错在这里啊,好久没有用AC自动机了
            node[tmp].id = 1;
        for(i = 0; i < MAXSON; i++) {
            if(node[tmp].next[i] == 0) {
                fail = node[tmp].fail;
                node[tmp].next[i] = node[fail].next[i];
                continue;
            }
            k = node[tmp].next[i];
            fail = node[tmp].fail;
            if(node[fail].next[i] != k)
                node[k].fail = node[fail].next[i];
            else
                node[k].fail = 0;
            q[++r] = k;
        }
    }
}
const double EPS = 1.0e-8;
bool dblcmp(double x) {
    if(fabs(x) < EPS)return 0;
    return x < 0 ? -1 : 1;
}
struct Point {
    double x, y;
} p[55];
double disPP(Point a, Point b) {
    double dx = a.x - b.x;
    double dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
}
const double INF = 1000000000.0 * 100000000.0;
double dp[55][5 * 110];
int main() {
    int n, m;
    int i, j, k;
    while(scanf("%d%d", &n, &m) != EOF) {
        if(n == 0 && m == 0)break;
        for(i = 1; i <= n; i++) {
            scanf("%lf%lf", &p[i].x, &p[i].y);
        }
        tot = -1;
        clr();
        while(m--) {
            ins();
        }
        get_fail();

        for(i = 0; i <= n; i++) {
            for(j = 0; j <= tot; j++) {
                dp[i][j] = INF;
            }
        }

        int h = node[0].next[0];

        if(node[h].id > 0) {
            puts("Can not be reached!");
            continue;
        }

        dp[1][h] = 0;
        double cost = 0;
        for(i = 1; i <= n; i++) {
            for(j = 0; j <= tot; j++) {
                if(dblcmp(dp[i][j] - INF) == 0)continue;
                for(k = i + 1; k <= n; k++) {
                    h = node[j].next[k - 1];
                    if(node[h].id)continue;
                    cost = disPP(p[i], p[k]) + dp[i][j];
                    if(cost < dp[k][h])dp[k][h] = cost;
                }
            }
        }

        double ans = INF;
        for(i = 0; i <= tot; i++) {
            if(dp[n][i] < ans)ans = dp[n][i];
        }

        if(dblcmp(INF - ans) != 0)printf("%.2f\n", ans);
        else puts("Can not be reached!");

    }
    return 0;
}


网友评论    (发表评论)

共1 条评论 1/1页

发表评论:

评论须知:

  • 1、评论每次加2分,每天上限为30;
  • 2、请文明用语,共同创建干净的技术交流环境;
  • 3、若被发现提交非法信息,评论将会被删除,并且给予扣分处理,严重者给予封号处理;
  • 4、请勿发布广告信息或其他无关评论,否则将会删除评论并扣分,严重者给予封号处理。


扫码下载

加载中,请稍后...

输入口令后可复制整站源码

加载中,请稍后...