2009 Google Code Jam Qualification Round 题解

本文内容遵从CC版权协议 转载请注明出自:   http://blog.csdn.net/masterluo

 

Problem A Site:   http://code.google.com/codejam/contest/dashboard?c=90101#s=p0

思路:把每个模式的每位上的字母都记录下来,然后对于每个单词都来进行一次查询即可。如果每于某个单词,每一位都在模式的某一位上,即它出现过。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <fstream>
#include <cstdio>
using namespace std;

int L , D , N;
ifstream in( "in.txt");
ofstream out( "out.txt");

string str [ 5001 ];
string pattern;
bool used [ 20 ][ 30 ];

int main() {
    in >> L >> D >> N;   
    for( int i = 0; i < D; ++ i) {
        in >> str [ i ];
    }

    for( int i = 0; i < N; ++ i) {
        memset( used , false , sizeof( used));
        in >> pattern;
        int start = 0;
        for( int j = 0; pattern [ j ]; ++ j) {
            if( pattern [ j ] == '(') {
                int v = j + 1;

                while( true) {
                    if( pattern [ v ] == ')') {
                        break;
                    }
                    used [ start ][ pattern [ v ] - 'a' ] = true;
                    ++ v;
                }
                j = v;
            } else {
                used [ start ][ pattern [ j ] - 'a' ] = true;
            }
            ++ start;
        }
        int ans = 0;
        for( int k = 0; k < D; ++ k) {
            bool flag = true;
            for( int j = 0; str [ k ][ j ]; ++ j) {
                if( used [ j ][ str [ k ][ j ] - 'a' ] == false) {
                    flag = false;
                    break;
                }
            }
            if( flag)
                ++ ans;
        }
        out << "Case #" << ( i + 1) << ": " << ans << endl;
       
    }
    return 0;

}

Problem B Site:   http://code.google.com/codejam/contest/dashboard?c=90101#s=p1

思路:先一次遍边把所有流向的方向记录下来同时把sink点记录下来。第二次遍边把流向sink点的点与sink点绑定为同一个块,再把流向上一点的点再绑定为同一块,这样就把每一块记录下来。同时,对于出现在越前的块给定越小的字母即可。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <iomanip>
#include <vector>
#include <fstream>
#include <map>
#include <cstdio>
#include <stack>
using namespace std;

int T , W , H;

ifstream in( "in.txt");
ofstream out( "out.txt");

struct Node {
    int h;
    vector < pair < int , int > > dir;
} mapp [ 101 ][ 101 ];

vector < pair < int , int > > sink;

#define MAX 100000

int off [ 4 ][ 2 ] = { - 1 , 0 , 0 , - 1 , 0 , 1 , 1 , 0 };
int edge [ 101 ][ 101 ];

bool check( int w , int h) {
    if( w >= 0 && w < W && h >= 0 && h < H)
        return true;
    return false;
}

int main() {
    in >> T;
    int TT = 1;
    for( int v = 0; v < T; ++ v) {
        in >> W >> H;
        for( int i = 0; i < W; ++ i) {
            for( int j = 0; j < H; ++ j) {
                in >> mapp [ i ][ j ]. h;
                mapp [ i ][ j ]. dir . clear();
            }
        }
        sink . clear();

        for( int i = 0; i < W; ++ i) {
            for( int j = 0; j < H; ++ j) {
                int H = MAX , x , y;
                for( int k = 0; k < 4; ++ k) {
                    int xx = i + off [ k ][ 0 ], yy = j + off [ k ][ 1 ];
                    if( check( xx , yy) && mapp [ xx ][ yy ]. h < H) {
                        H = mapp [ xx ][ yy ]. h;
                        x = xx;
                        y = yy;
                    }
                }
                if( H < mapp [ i ][ j ]. h) {
                    mapp [ x ][ y ]. dir . push_back( pair < int , int >( i , j));
                } else {
                    sink . push_back( pair < int , int >( i , j));
                }
            }
        }

        memset( edge , 0 , sizeof( edge));

        for( int i = 0; i < sink . size(); ++ i) {
            int group = i + 1;
            stack < pair < int , int > > tp;
            tp . push( sink [ i ]);
            while( ! tp . empty()) {
                pair < int , int > pr = tp . top();
                tp . pop();
                edge [ pr . first ][ pr . second ] = group;
                for( int j = 0; j < mapp [ pr . first ][ pr . second ]. dir . size(); ++ j) {
                    tp . push( mapp [ pr . first ][ pr . second ]. dir [ j ]);
                }
            }
        }
        map < int , char > maps;
        map < int , char >:: iterator itr;
        char ch = 'a';
        for( int i = 0; i < W; ++ i) {
            for( int j = 0; j < H; ++ j) {
                itr = maps . find( edge [ i ][ j ]);
                if( itr == maps . end()) {
                    maps [ edge [ i ][ j ]] = ch;
                    ++ ch;
                }
            }
        }

        out << "Case #" << TT << ":" << endl;
        for( int i = 0; i < W; ++ i) {
            for( int j = 0; j < H; ++ j) {
                out << maps [ edge [ i ][ j ]];
                if( j < H - 1) {
                    out << " ";
                } else {
                    out << endl;
                }
            }
        }
        ++ TT;

    }
    return 0;
}

Porblem C Site:  http://code.google.com/codejam/contest/dashboard?c=90101#s=p2

思路:可以记录到达第K个字母时满足条件的长度为1,2,3,4,……19的字串有多少种,如果某个字母与其中第K个字母相同,再更新长度为K+1的子串的个数。最后所有长度为19的子串即是结果。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <iomanip>
#include <fstream>
#include <cstdio>
using namespace std;

int L;
ifstream in( "in.txt");
ofstream out( "out.txt");

char str [ 508 ];
#define MOD 10000

int CNT [ 508 ][ 19 ];

char buff [ 508 ];

#define SIZE 502

int main() {
    in . getline( buff , SIZE);
    L = atoi( buff);

    char ch [ 22 ] = "welcome to code jam";

    for( int i = 0; i < L; ++ i) {
        in . getline( str , SIZE);
        memset( CNT , 0 , sizeof( CNT));
        for( int j = 0; str [ j ]; ++ j) {
            if( j == 0) {
                if( str [ j ] == ch [ 0 ]) {
                    CNT [ 0 ][ 0 ] = 1;
                }
            } else {
                for( int k = 0; ch [ k ]; ++ k) {
                    CNT [ j ][ k ] = CNT [ j - 1 ][ k ];
                    CNT [ j ][ k ] %= MOD;
                    if( str [ j ] == ch [ k ]) {
                        if( k == 0) {
                            CNT [ j ][ 0 ] += 1;
                        } else {
                            CNT [ j ][ k ] += CNT [ j - 1 ][ k - 1 ];
                        }
                    }
                }
            }
        }
        int ans = ( CNT [ strlen( str) - 1 ][ strlen( ch) - 1 ] % MOD);
        out << "Case #" << ( i + 1) << ": " << setw( 4) << setfill( '0') << ans << endl;
       
    }
    return 0;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值