本文内容遵从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;
}
#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;
}
#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;
}
#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;
}