题解---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 }
View Code

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 }
View Code

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 }
View Code

这代码更短,用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 }
View Code

 

 

 

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 }
View Code

 

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 }
View Code

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 }
View Code

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 }
View Code

 

 

 

 

 

 

如果还有什么不懂的,请在ACM群戳我QQ,@14林煜竣

 

posted @ 2015-12-20 23:46  YujunLin  阅读(1574)  评论(2编辑  收藏  举报