• ACM ICPC 2008–2009 NEERC MSC A, B, C, G, L


    这套题是我上周日, 就是前天打得一场组队赛, 题目不太好找

    题目链接:http://codeforces.com/gym/100861 在virtual judge 上也可以提交哦!

    A ACM ICPC Rules:

      题目大意: 有很多所高校参加预选赛, 并在预选赛取得了排名, 但是对于每所学校, 除了MSU有4个名额之外其他大学只有两个名额( 也就是说, 只有每个大学的前2名进决赛(MSU前四名)&& 最多有10个队伍进入决赛), 高中队伍不能进入决赛。 给出预选赛的排名, 输出可以进入决赛的名单,( 最多十个 )

      题目分析: 这道题还是看题解出来的, 感觉自己做的题太少了, 很多题能做出来就是做的方法添麻烦, 所以以后要多做题夯实, 首先如果遇到"SCH"就continue,  创建一个MAP<string, int>记录每种字符串出现的次数, 再创建一个vector<pair<string, string>> V 储存进入MSU 的排名。

     

    #include <iostream>
    #include <vector>
    #include <string>
    #include <map>
    #include <algorithm>
    using namespace std;
    
    vector<pair<string, string>> V;
    map<string, int> MAP;
    
    int main() {
        int n;
        while( cin >> n ) {
            int lim = 0;
            for( int i = 1; i <= n; i++ ) {
                string a, b;
                cin >> a >> b;
                if( a == "SCH" ) continue;
                else {
                    if( a == "MSU" ) lim = 4;
                    else lim = 2;
                }
                if( MAP[a] < lim ) {
                    MAP[a]++;
                    V.push_back( make_pair( a, b ) );
                }
            }
            int ans1 = min( 10, (int)V.size() );
            cout << ans1 << endl;
            for( int i = 0; i < ans1; i++ ) {
                cout << V[i].first << " ";
                cout << V[i].second << endl;
            }
        }
        return 0;
    }
    View Code

    G  Genesis Project:

      题目大意:给若干个点, 每两个点会生成一个新的点, 位置是两点连线的中点, 当前点都有"孩子"后当前点才会消失, 发生两个点的位置正好的重合的情况的“繁殖次数”是多少?

      题目分析: 首先要知道任意四边形的中点一定是平行四边形, 而平行四边形对角连线的中点重合 , 所以说,当点数大于4的时候, 最多繁殖次数就为2!妈的这点要是想到早就做上来了, 还是太蠢, 做的题实在是太少!然后答案为1的就是一个点恰好在两个点的中点的位置上, ( n >= 4 ) , 当只有 <= 3 个点的时候, 无论怎样都不可能重合!( 但是有一种特殊情况就是三个点 , 其中一点是另外两个点的中点, 这时本来应该输出1的, 但是没特殊处理也给过了(可能是数据水) )

      然后再说一下怎么找到两点重合, 首先建一个pair< int, int > P 的SET容器 , 来储存点的x , y坐标, 然后将P 推入SET 中, 最后两两枚举, 如果 SET.count( P ) == 1 就break掉然后输出1; 如果 n <= 3 则输出0 ; 其余的就用以上方法寻找, 如果寻找未果就输出2~!

      附上代码:

    #include <cstdio>
    #include <set>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    set< pair< int, int > > S;
    
    pair< int, int > a[1004];
    int n;
    
    
    
    int main() {
    
        scanf( "%d", &n );
        S.clear();
        memset( a, 0, sizeof( a ) );
        for( int i = 1; i <= n; i++ ) {
            scanf( "%d%d", &a[i].first, &a[i].second );
        }
        
        if( n <= 3 ) {
            printf( "0\n" );
            return 0;
        }
        for( int i = 1; i <= n; i++ ) {
            for( int j = i + 1; j <= n; j++ ) {
                pair< int, int > P;
                P = make_pair( a[i].first + a[j].first, a[i].second + a[j].second );
                if( S.count( P ) ) {
                    printf( "1\n" );
                    return 0;
                }
                S.insert( P );
            }
        }
        printf( "2\n" );
        return 0;
    }
    View Code

    L. Lucky Bonds:

      题目大意:给出Lucky number 的定义, 对于前N个数字和后N个数字之和相等, 比如“1340” 1 + 3 = 4 + 0 则这个数字就是Lucky Number,显然数字的位数为2 * N 。 输入一个N, 求长度为2 * N  最大连续非幸运数区间的左区间和右区间。 

     

      题目分析: 这道题是个构造题, 但是首先看到N的范围很小 , 1 ~ 10, 所以在想能不能打表将结果打出来, 暴力很简单, 当N  = 1 , 2, 3 的时候答案分别是 89, 98; 9899, 9998;

    998999, 999998; 所以后面的结果直接打表出来就可以了, 代码很丑。

     

      然后就是构造方法, 很明显这道题是一个special judge, 所以我以8 , 9为例, 来构造答案, 假设N = 3,  右端点就是999998, 左端点就为从999998 往左数的第一个幸运数字后的非幸运数字( 有些拗口 , 但是仔细想想还是能想明白 ) ,后三位和为 9 + 9 + 8, 所以前三位只能是8 + 9 + 9 , 9 + 8 + 9,  9 + 9 + 8 , 又因为9 9 8 组合是最靠近999998的( 向左数的第一个lucky number ) 所以构造方法就是, 左区间的端点值为第 N + 1 位为8, 其余为9 :

     

    附上史上最丑的代码,。。。。。。。。

     

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    using namespace std;
    
    string ans[30] = {
        " ", " ",
        "89", "98",
        "9899", "9998",
        "998999", "999998",
        "99989999", "99999998",
        "9999899999", "9999999998",
        "999998999999", "999999999998",
        "99999989999999", "99999999999998",
        "9999999899999999", "9999999999999998",
        "999999998999999999", "999999999999999998",
        "99999999989999999999", "99999999999999999998"
    };
    
    int main() {
        int n;
        while( cin >> n ) {
            cout << ans[2*n] << endl << ans[2*n+1] << endl;
        }
        return 0;
    }
    View Code

      还有两道题, 过段时间补全! 

  • 相关阅读:
    OI竞赛常见错误总结
    lis最长上升子序列o(nlogn)优化
    链表及其简单应用
    栈及其简单应用
    哈希表Hash:概念与基本操作
    队列及其简单应用
    poj1418 Viva Confetti 判断圆是否可见
    poj1981 Circle and Points 单位圆覆盖问题
    poj2187 Beauty Contest(旋转卡壳)
    poj2932 Coneology (扫描线)
  • 原文地址:https://www.cnblogs.com/FriskyPuppy/p/5998386.html
Copyright © 2020-2023  润新知