电子科技大学实验中学PK赛(一)比赛题解
比赛来源:第十四届重庆大学程序设计大赛暨西南地区高校邀请赛现场初赛
比赛地址:http://qscoj.cn/contest/24/
A. Comb 自述
分析:统计ACM在题目描述中出现的次数,认真数一遍就好了,答案就是比赛标题中的14.
官方标程:
#include <cstdio> int main() { puts("14"); return 0; }
我的AC代码:
#include<stdio.h> int main() { printf("14\n"); return 0; }
B. Comb 数学
分析:超级水题,我们知道5的任何正数次方都是5,唯一的坑就是5的0次方是1,只要加一个判断就行。
官方标程:
#include <cstdio> int main() { int t; scanf("%d", &t); while(t--) { int x; scanf("%d", &x); printf("%d\n", x ? 5 : 1); } return 0; }
我的AC代码:
#include<stdio.h> int main() { int T,x; scanf("%d",&T); while(T--) { scanf("%d",&x); if (x) printf("5\n"); else printf("1\n"); } return 0; }
C. Comb 找零
分析:题目里说Comb里的每个钱袋子都是2的x次幂,所以要正好凑成n数量的钱,就得将n转化为二进制统计其中1的数量,就是最少的钱袋数。当然,一个装2的x次幂的钱袋也可以拆成2个装2的x-1次幂的钱袋,但那样的话会让钱袋的数量更多。所以统计n转化成二进制其中1的数量就是最佳答案。注意n的数据范围为10^19,就比long long大了一点,我想用double发现精度会有问题,然后写了个高精度过了这个题,看了官方标程才想起还有unsigned long long这种东西。官方标程中的__builtin_popcountll(x)这个函数就是返回x转化成二进制后其中1的个数。
官方标程:
#include <cstdio> int main() { int t; scanf("%d", &t); while(t--) { unsigned long long x; scanf("%llu", &x); printf("%d\n", __builtin_popcountll(x)); } return 0; }
我的AC代码:
#include<bits/stdc++.h> using namespace std; int main() { int T,i,cnt,len; int a[20]; long long n,j; string s,s0; cin>>T; s0="9223372036854775808"; while(T--) { cin>>s;len=s.length();cnt=0; memset(a,0,sizeof(a)); for(i=0;i<len;i++) a[len-1-i]=s[i]-48; if (len==20 || (len==19 && s>=s0)) { cnt++; for(i=0;i<=18;i++) a[i]-=s0[18-i]-48; for(i=0;i<=18;i++) { if (a[i]<0) {a[i]+=10;a[i+1]--;} } } j=1e18;n=0; for(i=18;i>=0;i--) { n+=j*a[i]; j/=10; } for(i=62;i>=0;i--) { j=(1ll<<i); cnt+=n/j;n%=j; } printf("%d\n",cnt); } return 0; }
D. Comb 寻路
分析:棋盘的大小不大,只有100*100,所以可以采用BFS的方法,用dp[i][j]记录点从起点到点(i,j)的最短时间,一开始将怪物及怪物周边的空地标为-1;将其他点标为inf,将起点标为0,从起点开始BFS.注意从空地到空地需要花费时间1,从空地到墙或从墙到空地需要花费时间2,从墙到墙需要花费时间3.搜索完毕后判断终点的dp[i][j]值,如果为-1或inf则输出“Oh, Comb can't go out”,否则就输出该答案。
官方标程:
// // Created by TaoSama on 2017-05-01 // Copyright (c) 2017 TaoSama. All rights reserved. // #pragma comment(linker, "/STACK:102400000,102400000") #include <bits/stdc++.h> using namespace std; #define pr(x) cerr << #x << " = " << x << " " #define prln(x) cerr << #x << " = " << x << endl const int N = 1e2 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7; int n, m; char s[N][N]; int f[N][N], in[N][N]; int main() { #ifdef LOCAL freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin); // freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); int t; scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) scanf("%s", s[i] + 1); int sx, sy, tx, ty; static const int d[][2] = { -1, 0, 0, -1, 1, 0, 0, 1}; auto inBound = [&](int x, int y) { return x >= 1 && x <= n && y >= 1 && y <= m; }; for(int i = 1; i <= n; ++i) { for(int j = 1; j <= m; ++j) { if(s[i][j] == 'C') sx = i, sy = j; else if(s[i][j] == 'E') tx = i, ty = j; else if(s[i][j] == 'M') { for(int k = 0; k < 4; ++k) { int x = i + d[k][0], y = j + d[k][1]; if(inBound(x, y) && s[x][y] == '*') s[x][y] = 'X'; } } } } bool can = true; for(int k = 0; k < 4; ++k) { int x = sx + d[k][0], y = sy + d[k][1]; if(inBound(x, y) && s[x][y] == 'M') can = false; } for(int k = 0; k < 4; ++k) { int x = tx + d[k][0], y = ty + d[k][1]; if(inBound(x, y) && s[x][y] == 'M') can = false; } if(!can) {puts("Oh, Comb can't go out"); continue;} queue<pair<int, int>> q; q.push({sx, sy}); memset(f, 0x3f, sizeof f); memset(in, false, sizeof in); f[sx][sy] = 0; in[sx][sy] = true; while(q.size()) { int x, y; tie(x, y) = q.front(); q.pop(); in[x][y] = false; for(int k = 0; k < 4; ++k) { int nx = x + d[k][0], ny = y + d[k][1]; if(!inBound(nx, ny) || s[nx][ny] == 'X') continue; int c = s[nx][ny] == '#' ? 3 : 1; if(f[nx][ny] > f[x][y] + c) { f[nx][ny] = f[x][y] + c; if(!in[nx][ny]) in[nx][ny] = true, q.push({nx, ny}); } } } if(f[tx][ty] == INF) puts("Oh, Comb can't go out"); else printf("%d\n", f[tx][ty]); } return 0; }
我的AC代码:
#include<bits/stdc++.h> using namespace std; const int inf=0x3f3f3f3f; vector< pair<int,int> > v[10010]; int fx[4]={-1,1,0,0}; int fy[4]={0,0,-1,1}; int main() { int T,n,m,xc,yc,xe,ye,i,j,k,s; int x,y,xx,yy,cnt; int dp[110][110]; char c[110][110]; cin>>T; while(T--) { cin>>n>>m; for(i=1;i<=n;i++) for(j=1;j<=m;j++) dp[i][j]=inf; for(i=0;i<=10000;i++) v[i].clear(); for(i=1;i<=n;i++) for(j=1;j<=m;j++) { cin>>c[i][j]; if (c[i][j]=='C') {xc=i;yc=j;} if (c[i][j]=='E') {xe=i;ye=j;} } for(i=1;i<=n;i++) for(j=1;j<=m;j++) { if (c[i][j]=='M') { dp[i][j]=-1; for(k=0;k<4;k++) { xx=i+fx[k]; yy=j+fy[k]; if (xx<1 || xx>n || yy<1 || yy>m) continue; if (c[xx][yy]=='#') continue; dp[xx][yy]=-1; } } } if (dp[xc][yc]==-1 || dp[xe][ye]==-1) { printf("Oh, Comb can't go out\n"); continue; } v[0].push_back(make_pair(xc,yc));dp[xc][yc]=0;cnt=0; while(1) { for(i=0;i<v[cnt].size();i++) { s=1;x=v[cnt][i].first;y=v[cnt][i].second; if (dp[x][y]<cnt) continue; if (c[x][y]=='#') s++; for(j=0;j<4;j++) { xx=x+fx[j];yy=y+fy[j]; if (xx<1 || xx>n || yy<1 || yy>m) continue; if (dp[xx][yy]==-1) continue; if (c[xx][yy]=='#') s++; if (dp[xx][yy]>cnt+s) { dp[xx][yy]=cnt+s; v[cnt+s].push_back(make_pair(xx,yy)); } if (c[xx][yy]=='#') s--; } } if (cnt>=2 && !v[cnt].size() && !v[cnt-1].size() && !v[cnt-2].size()) break; cnt++; } if (dp[i][j]==-1) printf("Oh, Comb can't go out\n"); else printf("%d\n",dp[xe][ye]); } return 0; }