题解---2015年浙江理工12月校赛
A: 孙壕请一盘青岛大虾呗
A题比较容易,因为范围只有10,所以暴力搜索一下就好了,简单递归题
1 #include<cstdio> 2 #include<cstring> 3 int dfs(int n, int m, int num){ 4 if(n == 0 && m == 0 && num == 0){ 5 return 1; 6 } 7 if(n == -1 || m == -1 || num == 0) return 0; 8 return dfs(n-1, m, num << 1) + dfs(n, m-1, num-1); 9 } 10 int main(){ 11 int n, m; 12 while(scanf("%d%d", &n, &m) != EOF){ 13 printf("%d\n", dfs(n, m, 2)); 14 } 15 }
B: 七龙珠
B题,简单的排序,不多说了,注意一下第7个数不要拿去排序就好了
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 int a[7]; 5 int b[7]; 6 int work(){ 7 sort(a, a+6); 8 sort(b, b+6); 9 for(int i = 0; i < 7; i++){ 10 if(a[i] != b[i]) return 0; 11 } 12 return 1; 13 } 14 int main(){ 15 while(scanf("%d", &a[0]) != EOF){ 16 for(int i = 1; i < 7; i++) scanf("%d", &a[i]); 17 for(int i = 0; i < 7; i++) scanf("%d", &b[i]); 18 puts(work() ? "yes" : "no"); 19 } 20 }
C: String Game
C题,比较字符串,a字符串,与b字符串,可以证明的b字符串在a字符串中间,才是Alice赢,因为Bob从左边拿一个,Alice就可以从右边拿一个,Bob从右边拿一个,Alice就可以从左边拿一个,保证b字符串一直在a字符串中间,但是还有两种情况,就是如果有两个字符串与b匹配,那么只要这两个字符串关于a的中间对称,且两个字符串的位置差不超过2,那么也是Alice赢,因为,Bob拿完一个后,Alice可以在相同方向拿,所以字符串可以从中间向左(或右)偏移1格
比如
a:xxx
b:xx
a:xyxyxyx
b:xyxyx
这些都是Alice赢,那么只要for几遍比较一下就好了,具体见代码
1 #include<cstdio> 2 #include<cstring> 3 char str1[500005]; 4 char str2[500005]; 5 int len1, len2; 6 int work(){ 7 if(len1 < len2) return 0; 8 int pos = (len1 - len2) >> 1; 9 int flag; 10 if(len1 % 2 != len2 % 2){//奇偶不同 11 flag = 1; 12 for(int i = 0; i < len2; i++){ 13 if(str2[i] != str1[pos+i]){ 14 flag = 0; 15 break; 16 } 17 } 18 for(int i = 0; i < len2; i++){ 19 if(str2[i] != str1[pos+i+1]){ 20 flag = 0; 21 break; 22 } 23 } 24 if(flag == 1) return 1; 25 } 26 else{//奇偶相同 27 flag = 1; 28 for(int i = 0; i < len2; i++){ 29 if(str2[i] != str1[pos+i]){ 30 flag = 0; 31 break; 32 } 33 } 34 if(flag == 1) return 1; 35 if(len1 - len2 >= 2){ 36 flag = 1; 37 for(int i = 0; i < len2; i++){ 38 if(str2[i] != str1[pos+i-1]){ 39 flag = 0; 40 break; 41 } 42 } 43 for(int i = 0; i < len2; i++){ 44 if(str2[i] != str1[pos+i+1]){ 45 flag = 0; 46 break; 47 } 48 } 49 if(flag == 1) return 1; 50 } 51 } 52 return 0; 53 } 54 int main(){ 55 int T; 56 scanf("%d", &T); 57 while(T--){ 58 scanf("%s%s", str1, str2); 59 len1 = strlen(str1); 60 len2 = strlen(str2); 61 puts(work() ? "Alice" : "Bob"); 62 } 63 }
这代码更短,用string类
1 #include<cstdio> 2 #include<string.h> 3 #include<iostream> 4 using namespace std; 5 int lena,lenb; 6 string a,b; 7 bool fun(){ 8 if(lena < lenb) return 0; 9 int pos = (lena - lenb) >> 1; 10 if(lena % 2 != lenb % 2){ 11 if(a.find(b,pos) == pos && a.find(b,pos+1) == pos+1 ) return 1; 12 }else{ 13 if(a.find(b,pos) == pos) return 1; 14 if(lena - lenb >= 2) 15 if(a.find(b,pos-1) == pos-1 && a.find(b,pos+1)==pos+1) return 1; 16 } 17 return 0; 18 } 19 int main(){ 20 int T; 21 scanf("%d",&T); 22 while(T--){ 23 cin >> a >> b; 24 lena = a.length(); 25 lenb = b.length(); 26 puts(fun() ? "Alice" : "Bob"); 27 } 28 }
D: One-Way Roads
我不会,我不会,我不会,重要的事要说三遍
请右拐至ACM群戳@12章铭铭
找铭铭姐教你
铭铭姐代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <vector> 5 6 const int N = 50 + 5; 7 8 int head[N],etot; 9 struct Edge { 10 int v,next; 11 } g[N * N]; 12 int n,m; 13 14 bool vis[N * N]; 15 16 void add_edge(int u,int v) { 17 g[etot].v = v; g[etot].next = head[u]; head[u] = etot ++; 18 } 19 20 std::vector<std::pair<int,int> > answer; 21 22 void dfs(int u) { 23 for (int &i = head[u]; i != -1; ) { 24 if (vis[i >> 1]) { 25 i = g[i].next; 26 continue; 27 } 28 int v = g[i].v; 29 vis[i >> 1] = true; 30 answer.push_back(std::make_pair(u,v)); 31 i = g[i].next; 32 dfs(v); 33 } 34 } 35 36 bool graph[N][N]; 37 38 bool work() { 39 answer.clear(); 40 memset(vis,0,sizeof(vis)); 41 dfs(0); 42 memset(graph,0,sizeof(graph)); 43 for (int i = 0; i < answer.size(); ++ i) { 44 graph[answer[i].first][answer[i].second] = true; 45 } 46 for (int k = 0; k < n; ++ k) 47 for (int i = 0; i < n; ++ i) 48 for (int j = 0; j < n; ++ j) 49 graph[i][j] |= graph[i][k] & graph[k][j]; 50 for (int i = 0; i < n; ++ i) { 51 for (int j = 0; j < n; ++ j) { 52 if (i != j && graph[i][j] == false) { 53 return false; 54 } 55 } 56 } 57 return true; 58 } 59 60 int main() { 61 int cas; 62 scanf("%d",&cas); 63 while (cas--) { 64 scanf("%d%d",&n,&m); 65 memset(head,-1,sizeof(head)); etot = 0; 66 for (int i = 0; i < m; ++ i) { 67 int a,b; 68 scanf("%d%d",&a,&b); a --; b --; 69 add_edge(a,b); 70 add_edge(b,a); 71 } 72 if (!work()) { 73 puts("NO"); 74 } else { 75 puts("YES"); 76 for (int i = 0; i < answer.size(); ++ i) { 77 printf("%d %d\n",answer[i].first + 1,answer[i].second + 1); 78 } 79 } 80 } 81 }
E: Power Eggs
动态规划题
dp[i][j] = x
表示i个鸡蛋,扔j次,最多能够判断出多少楼层
因为我算了0层,所以最后用n+1比较
PS:这题要开longlong,否则会WA
1 #include<cstdio> 2 long long dp[35][35]; 3 int ans; 4 long long n; 5 int k; 6 int main(){ 7 dp[0][0] = 1; 8 for(int i = 1; i <= 32; i++){ 9 dp[i][1] = 2; 10 dp[1][i] = i+1; 11 dp[i][i] = dp[i-1][i-1] * 2; 12 } 13 for(int i = 2; i <= 32; i++){ 14 for(int j = 2; j <= i; j++){ 15 dp[i][j] = dp[j][j]; 16 } 17 for(int j = i+1; j <= 32; j++){ 18 dp[i][j] = dp[i][j-1] + dp[i-1][j-1]; 19 } 20 } 21 int T; 22 scanf("%d", &T); 23 while(T--){ 24 scanf("%lld%d", &n, &k); 25 ans = -1; 26 for(int i = 1; i <= 32; i++){ 27 if(dp[k][i] >= n+1){ 28 ans = i; 29 break; 30 } 31 } 32 if(ans == -1){ 33 printf("Impossible\n"); 34 } 35 else{ 36 printf("%d\n", ans); 37 } 38 } 39 }
F: Landlocked
搜索题
bfs一遍,从海往中间标记路程就好了
最好把连在一起的块一起标记了
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 using namespace std; 6 queue <int> que[2]; 7 int n, m; 8 char map[1005][1005]; 9 int vis[1005][1005]; 10 int d[1005][1005]; 11 int dd[256]; 12 int dir[8][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}}; 13 bool ok(int x, int y){ 14 if(x < 0 || x >= n || y < 0 || y >= m || vis[x][y] == 1){ 15 return false; 16 } 17 return true; 18 } 19 void dfs(int x, int y, int val, char letter, int p){ 20 vis[x][y] = 1; 21 d[x][y] = val; 22 int ex, ey; 23 for(int i = 0; i < 8; i++){ 24 ex = x + dir[i][0]; 25 ey = y + dir[i][1]; 26 if(ok(ex, ey)){ 27 if(map[ex][ey] != letter){ 28 que[p].push(ex); 29 que[p].push(ey); 30 que[p].push(val + 1); 31 } 32 else{ 33 dfs(ex, ey, val, letter, p); 34 } 35 } 36 } 37 } 38 int main(){ 39 while(scanf("%d%d", &n, &m) != EOF){ 40 memset(vis, 0, sizeof(vis)); 41 memset(dd, 0x3f, sizeof(dd)); 42 for(int i = 0; i < n; i++){ 43 scanf("%s", map[i]); 44 } 45 for(int i = 0; i < n; i++){ 46 for(int j = 0; j < m; j++){ 47 if(map[i][j] == 'W'){ 48 que[0].push(i); 49 que[0].push(j); 50 que[0].push(-1); 51 } 52 } 53 } 54 int x, y, val; 55 for(int i = 0; !que[i].empty(); i ^= 1){ 56 while(!que[i].empty()){ 57 x = que[i].front(); que[i].pop(); 58 y = que[i].front(); que[i].pop(); 59 val = que[i].front(); que[i].pop(); 60 if(vis[x][y] == 1) continue; 61 dfs(x, y, val, map[x][y], i^1); 62 } 63 } 64 /*for(int i = 0; i < n; i++){ 65 for(int j = 0; j < m; j++){ 66 printf("%d\t", d[i][j]); 67 } 68 printf("\n"); 69 }*/ 70 for(int i = 0; i < n; i++){ 71 for(int j = 0; j < m; j++){ 72 dd[(int)map[i][j]] = min(dd[(int)map[i][j]], d[i][j]); 73 } 74 } 75 for(int i = 0; i < 256; i++){ 76 if(i == (int)'W') continue; 77 if(dd[i] == 0x3f3f3f3f) continue; 78 printf("%c %d\n", (char)i, dd[i]); 79 } 80 } 81 }
G: Jug Hard
通过推理可以发现,这题就是求a与b的最大公约数,然后看看d是不是这个约数的倍数
1 #include<cstdio> 2 int gcd(int a, int b){ 3 return b ? gcd(b, a%b) : a; 4 } 5 int main(){ 6 int T, a, b, d; 7 scanf("%d", &T); 8 while(T--){ 9 scanf("%d%d%d", &a, &b, &d); 10 puts(d % gcd(a, b) ? "No" : "Yes"); 11 } 12 }
如果还有什么不懂的,请在ACM群戳我QQ,@14林煜竣