zoukankan      html  css  js  c++  java
  • UVa 10635

    看题

    题目


    在nxn的棋盘上,王子和公主玩游戏。棋盘上的正方形编号为1、2、3 ... n * n,如下所示:
    Prince站在正方形1中,进行p跳跃,最后到达正方形n * n。他最多只能进入一个广场。因此,如果我们使用xp表示他输入的第p个平方,则x1,x2,... xp + 1都不同。注意,x1 = 1,xp + 1 = n * n。公主做类似的事情-站在方格1中,使q跳,最后到达方格n * n。我们使用y1,y2,... yq + 1表示序列,并且所有q + 1数均不同。
    下面的图2显示了一个3x3的正方形,这是Prince的可能路线,而Princess的路线则不同。
    王子按照以下顺序移动:1-> 7-> 5-> 4-> 8-> 3-> 9(黑色箭头),而公主按照以下顺序移动:1-> 4 -> 3-> 5-> 6-> 2-> 8-> 9(白色箭头)。
    国王-他们的父亲刚来。“为什么要分开走?你是兄弟姐妹!” 国王说:“忽略一些跳跃,确保你们一直在一起。”
    例如,如果王子忽略了他的第二,第三,第六跳,他将遵循以下路线:1-> 4-> 8->9。如果公主忽略了她的第三,第四,第五,第六跳,她将遵循相同的路线:1-> 4-> 8-> 9(常见路线如图3所示),因此满足了国王(如上所示)。国王想知道他们可以一起走的最长路线,你能告诉他吗?
    输入值
    输入的第一行包含一个整数t(1 <= t <= 10),后面是测试用例的数量。对于每种情况,第一行包含三个整数n,p,q(2 <= n <= 250,1 <= p,q <n * n)。第二行包含p + 1个不同的整数,范围为[1..n * n],即Prince的序列。第三行包含q + 1个不同的整数,范围为[1..n * n](公主的序列)。

    输出量
    对于每个测试案例,请打印案例编号和最长路径的长度。查看输出以获取样本输入以获取详细信息。



    样本输入     
                         
    1


    3 6 7


    1 7 5 4 8 3 9


    1 4 3 5 6 2 8 9


    样本输出

    Case 1:4


    一看是LCS, 于是写了上去,然后,就没有然后了...

    显然,LCS它n^2这个效率肯定要TLE的...

    那么考虑一个极妙的方法。

    先看题目,答案要求一起走,那么也就是说在两个数组中,如果有 a[i]==b[j], 那么a[i]与b[j]就 有可能被选入最后答案。

    那么,我们不妨标记出a走到   b到过的格子 或 b要到的格子   的时间。a 第 i 步走到了 n, b 第 j 步也走到了 n, 那么标记 b[j] 为 i。如果 b走到的格子, a 却没有走到,那么这个格子就不可能成为最后共同走的路径的一部分。

    可以用map[i]存储第一个字符串a[]中 值为i 编号,用f[i]来记录a走到 ab都可以走到的格子 的时间。当读入b[i]时,如果map[b[i]]被更改了(即存储了a数组某个值的编号), 那么就说明b[i]与a数组中某个值(a[j])相等,根据上面的分析,b[i]就有可能被选入最后答案。让map[b[i]] 存储的编号,也就是a走到相同格子的 时间,赋值给f[++cnt]。再用二分求 f 数组LIS即可。

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAXN = 62500 + 3;
    int n, p, q, ans, map[MAXN], f[MAXN], low[MAXN];
    
    int main(){
        int T;
        scanf("%d",&T);
        for(int t=1;t<=T;t++){
            memset(map, 0, sizeof(map));
            memset(f, 0, sizeof(f));
            scanf("%d%d%d",&n,&p,&q);
            int a, b;
            int cnt = 0;
            for(int i=1;i<=p+1;i++){
                scanf("%d",&a);//这里可以直接用变量
                map[a] = i;
            }
            for(int i=1;i<=q+1;i++){
                scanf("%d",&b);
                if(map[b]){
                    f[++cnt] = map[b];
                }
            }
            
            memset(low, 0x3f, sizeof(low));
            low[1] = f[1];
            ans = 1;
            for(int i=2;i<=cnt;i++){//二分求LIS
                if(f[i] > low[ans]){
                    low[++ans] = f[i];
                }else{
                    int c = lower_bound(low+1, low+ans+1, f[i])-low;
                    low[c] = f[i];
                }
            }
            printf("Case %d: %d
    ",t,ans);
        }
        return 0;
    }
  • 相关阅读:
    Laya页面嵌套和Scene.destory导致的Bug
    Laya的滚动容器Panel+HBox
    Laya的对象唯一标识
    Android自带的TTS功能
    一步一步学android之控件篇——ListView基本使用
    android surfaceView 的简单使用 画图,拖动效果
    Android 数据分析系列一:sharedPreferences
    Android Service总结
    android中碰撞屏幕边界反弹问题
    Android开发:setAlpha()方法和常用RGB颜色表----颜色, r g b分量数值(int), 16进制表示 一一对应
  • 原文地址:https://www.cnblogs.com/Siegfried-L/p/12668907.html
Copyright © 2011-2022 走看看