2016中北大學ACM程式設計新生賽題解
新生賽題目地址
a or an
輸入字串後判斷第一個字元是不是’a’,’e’,’i’,’o’,’u’,即可。
#include<algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
const int MOD = 100000000;
int main()
{
char a[100];
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)
{
scanf("%s",a);
//判斷首字元
if(a[0]=='a'||a[0]=='e'||a[0]=='i'||a[0]=='o'||a[0]=='u')
{
printf("an\n");
}
else{
printf("a\n" );
}
}
}
return 0;
}
刪數問題
列舉數字a[i],再判斷數字a[i]是不是在a[i,i+s]中最小,如果不是就刪除,每刪除一個就使s減1,直到s等於0,或剩餘的數量小於總長度,那麼剩下的數字都要比前面的數字大,全部刪除。
#include<algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define INF (1<<30)
#define PI acos(-1.0)
const int MOD = 1000000007;
typedef long long ll;
using namespace std;
char a[1000];
int vis[1000];
int s;
int main()
{
while(scanf("%s",a)!=EOF)
{
scanf("%d",&s);
bool flag=false;
memset(vis,-1,sizeof(vis));
int len=strlen(a);
int h0=0;
for(int i=0;i<len;i++)//記錄陣列中0的個數,如果大於s就直接輸出0
{
if(a[i]=='0')
{
h0++;
}
}
if(s>=len-h0)
{
printf("0\n");
continue;
}
for(int i=0; i<len; i++)
{
int t=0;
for(int j=1;j<=s;j++)
{
if(a[i]>a[i+j])
{
vis[i]=0;
s--;
break;
}
}
if(i+s+1>len)//剩餘的數量小於總長度,那麼剩下的數字都要比前面的數字大,全部刪除。
{
len-=s;
break;
}
if(!s)//已經刪除完畢
{
break;
}
}
bool flag1=false;
for(int i=0; i<len; i++)
{
if(!flag1&&a[i]=='0')//跳過前導0
{
continue;
}
if(vis[i])
{
flag1=true;
printf("%c",a[i]);
}
}
if(!flag1)全部都是0時輸出0
{
printf("0");
}
printf("\n");
}
return 0;
}
潛入密室
找到通項公式f[i]=f[i-1]+3*i-1。先打出表,在二分搜尋。或是找到其他公式直接計算出來也可以。
#include<algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
const int MOD = 100000000;
long long n;
long long a[900005];
int main()
{
long long ans=0;
a[0]=0;
for(int i=1;i<=900000;i++)
{
ans+=i*3-1;
a[i]=ans;
}
while(scanf("%lld",&n)!=EOF)
{
int l=0,r=900000,mid,t=100;
while(t--)
{
mid=(l+r)/2;
if(a[mid]<=n&&n<a[mid+1])
{
ans=mid;
break;
}
if(a[mid]>n)
{
r=mid;
}
else
{
l=mid;
}
}
printf("%lld\n",ans);
}
return 0;
}
開鎖
先判斷字串是不是迴文,如果是,不管之後數值如何,它都是迴文。如果不是,就從陣列兩端分析如果每一個正串都對應的是一串逆序串就表明組合後是迴文。
#include<algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
const int MOD = 100000000;
char a[1000005];
int b[1000005];
int main()
{
int n;
while(scanf("%s",a)!=EOF)
{
bool flag=true;
int len=strlen(a);
for(int i=0;i<len/2;i++)
{
if(a[i]!=a[len-i-1])
{
flag=false;
}
}
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&b[i]);
}
if(flag)
{
printf("YES\n");
}
else
{
flag=true;
int l=0,r=n-1;
while(true)
{
if(l>r)
{
break;
}
if(b[l]*b[r]>0)
{
flag=false;
break;
}
if(abs(b[l])==abs(b[r]))
{
r--;
l++;
}
else if(abs(b[l])>abs(b[r]))
{
b[l]+=b[r];
r--;
}
else if(abs(b[l])<abs(b[r]))
{
b[r]+=b[l];
l++;
}
}
if(flag)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
}
return 0;
}
偷寶記
列舉每個左端點值的情況,把在a[i].x到a[i].x+x的所有y值放入陣列再排序,最後尺取出最優解。
#include<algorithm>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
struct node
{
int x, y;
};
bool cmp(node a, node b)
{
return a.x<b.x;
}
int n, x, y;
node a[1005];
int findd(int x, int y)
{
int maxn = 0;
int b[1005];
for (int i = 0, l = 0; i<n; i++)
{
if (a[i].x == a[l].x && i != l)
{
continue;
}
else
{
l = i;
}
int cnt = 0;
for (int j = l; j<n; j++)
{
if (a[i].x + x<a[j].x)
{
break;
}
b[cnt++] = a[j].y;
}
sort(b, b + cnt);
for (int j = 0, k = 0; j<cnt; j++)
{
while (k < cnt && b[j] + y >= b[k])
{
k++;
}
maxn = max(maxn, k - j);
}
}
return maxn;
}
int main()
{
while (cin >> n >> x >> y)
{
for (int i = 0; i<n; i++)
{
cin >> a[i].x >> a[i].y;
}
sort(a, a + n, cmp);
int ans = findd(x, y);
printf("%d\n", ans);
}
return 0;
}
密室逃脫
先按從上到下從左到右的順序把板子排序,儲存第一步後的兩種情況。列舉板子,有以下種情況:
1.到達一層。
2.佇列的點在板子左側。
3.點在板子上方。
4.點在板子右側。
5.點用完了。
6.點不是在板子上一行的。
7.點和板子同行。
對應不同情況進行處理。
也可以如程式碼2的方法處理:
從最高行開始列舉,判斷有沒有可達情況在上方,有的話判斷該點位置是不是在板子上,分別處理。
#include<algorithm>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
struct node
{
int h, r, l;
bool operator < (const node &t1) const
{
if (h != t1.h)
{
return h>t1.h;
}
else
{
return r<t1.r;
}
}
}no[1000005];
struct step
{
int h;
int x;
int s;
}ne, nel, ner;
int vis[1000005][2];
queue<step>q;
int n, h;
void reb(step s)
{
if (s.s == INF)
{
return;
}
if (vis[s.x][0] != s.h)
{
vis[s.x][0] = s.h;
vis[s.x][1] = s.s;
q.push(s);
}
}
int findd()
{
int t = 0, i = 0;
while(no[i].h == h)
{
i++;
}
nel.h = no[i].h;
nel.x = no[i].l;
nel.s = INF;
ner.h = no[i].h;
ner.x = no[i].r;
ner.s = INF;
while (!q.empty())
{
ne = q.front();
if (ne.h == 1)
{
ne.s++;
ne.h--;
vis[ne.x][0] = ne.h;
vis[ne.x][1] = ne.s;
}
else if (i >= n || ne.h>no[i].h + 1 || ne.x<no[i].l)
{
ne.s++;
ne.h--;
reb(ne);
}
else if (no[i].l <= ne.x&&ne.x <= no[i].r)
{
nel.s = min(nel.s, ne.x - no[i].l + 1 + ne.s);
ner.s = min(ner.s, no[i].r - ne.x + 1 + ne.s);
}
else
{
reb(ner);
reb(nel);
i++;
nel.h = no[i].h;
nel.x = no[i].l;
nel.s = INF;
ner.h = no[i].h;
ner.x = no[i].r;
ner.s = INF;
continue;
}
q.pop();
if (q.empty()&&nel.x!=INF)
{
reb(ner);
reb(nel);
i++;
nel.h = no[i].h;
nel.x = no[i].l;
nel.s = INF;
ner.h = no[i].h;
ner.x = no[i].r;
ner.s = INF;
}
}
int minn = INF;
for (int i = 0; i<1000005; i++)
{
if (vis[i][0] == 0)
minn = min(vis[i][1], minn);
}
return minn;
}
int main()
{
while (cin >> n)
{
while (!q.empty())
{
q.pop();
}
h = 0;
memset(vis, -1, sizeof(vis));
for (int i = 0, a, b, c; i<n; i++)
{
cin >> b >> a >>c;
no[i].h = a;
no[i].l = b;
no[i].r = b + c;
h = max(h, a);
}
sort(no, no + n);
ne.s = 0;
ne.h = no[0].h;
ne.x = no[0].l;
q.push(ne);
ne.s = no[0].r - no[0].l;
ne.h = no[0].h;
ne.x = no[0].r;
q.push(ne);
vis[no[0].l][0] = h;
vis[no[0].l][1] = 0;
vis[no[0].r][0] = h;
vis[no[0].r][1] = no[0].r - no[0].l;
printf("%d\n", findd());
}
return 0;
}
程式碼2
#include<algorithm>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int dp[1005][2005];
int vis[1005][2005][3];
int n,h;
int findd()
{
while(h)
{
h--;
for(int i=0; i<=2000; i++)
{
if(dp[h+1][i]!=-1)
{
if(vis[h][i][0]==0)
{
dp[h][i]=dp[h+1][i]+1;
}
else
{
if(dp[h][vis[h][i][1]]==-1)
{
dp[h][vis[h][i][1]]=i-vis[h][i][1]+dp[h+1][i]+1;
dp[h][vis[h][i][2]]=vis[h][i][2]-i+dp[h+1][i]+1;
}
else
{
dp[h][vis[h][i][1]]=min(i-vis[h][i][1]+dp[h+1][i]+1,dp[h][vis[h][i][1]]);
dp[h][vis[h][i][2]]=min(vis[h][i][2]-i+dp[h+1][i]+1,dp[h][vis[h][i][2]]);
}
}
}
}
}
int minn=INF;
for(int i=0; i<=2000; i++)
{
if(dp[0][i]!=-1)
minn=min(minn,dp[0][i]);
}
return minn;
}
void inid()
{
for(int i=0; i<=2000; i++)
{
if(vis[h][i][0])
{
dp[h][vis[h][i][1]]=0;
dp[h][vis[h][i][2]]=vis[h][i][2]-vis[h][i][1];
return;
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
h=0;
memset(vis,0,sizeof(vis));
memset(dp,-1,sizeof(dp));
for(int i=0,a,b,c; i<n; i++)
{
scanf("%d%d%d",&b,&a,&c);
if(a==0)
{
continue;
}
for(int i=0; i<=c; i++)
{
vis[a][b+i][0]=1;
vis[a][b+i][1]=b;
vis[a][b+i][2]=b+c;
}
h=max(h,a);
}
inid();
printf("%d\n",findd());
}
return 0;
}
郭姐分石子
有n個石子每次分出i個石子,使每次分出的石子大於等於上次分出的石子,最後遞迴查詢。
#include<algorithm>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int findd(int n,int m,int k)
{
int ans=0;
if(m==0)
{
if(n==0)
{
return 1;
}
else
{
return 0;
}
}
for(int i=k;i<=n;i++)
{
ans+=findd(n-i,m-1,i);
}
return ans;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
printf("%d\n",findd(n,m,1));
}
return 0;
}
笨 笨
簡單的排序。
#include<algorithm>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int main()
{
char a[10];
while(scanf("%s",a)!=EOF)
{
sort(a,a+3);
printf("%s\n",a);
}
return 0;
}
非洲來的郭姐
用錯排公式求解,第i點放的情況有n-1種,同時有恰好這點放的值的位置放上i,和其他情況。
#include<algorithm>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int findd(int n)
{
if(n<0)
{
return 0;
}
if(n==0)
{
return 1;
}
return (n-1)*(findd(n-2)+findd(n-1));
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
printf("%d\n",findd(n)+1);
}
return 0;
}
五子棋
列舉每個點的情況看看按一個方向搜過去能否有五子連珠的情況。
#include<algorithm>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
char mapp[200][200];
int D[4][2]={{1,1},{0,1},{-1,1},{1,0}};
int n,m,T;
bool check(char a,int x,int y)
{
for(int i=0;i<4;i++)
{
if(0>x+D[i][0]*4||x+D[i][0]*4>=n||0>y+D[i][1]*4||y+D[i][1]*4>=m)
{
continue;
}
bool flag=true;
for(int j=0;j<5;j++)
{
if(a!=mapp[x+D[i][0]*j][y+D[i][1]*j])
{
flag=false;
break;
}
}
if(flag)
{
return true;
}
}
return false;
}
char findd()
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(mapp[i][j]!='X')
{
if(check(mapp[i][j],i,j))
{
return mapp[i][j];
}
}
}
}
return 'A';
}
int main()
{
while(scanf("%d",&T)!=EOF)
{
for(int t=1;t<=T;t++)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
getchar();
scanf("%s",mapp[i]);
}
printf("Case %d:%c\n",t,findd());
}
}
return 0;
}
森林
假設怪物到出口的距離小於等於人過去的距離則必定相遇,如果大於則必定不相遇。所以從出口反向bfs即可。
#include<algorithm>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
char mapp[1000][1000];
int vis[1000][1000];
int n,m;
int D[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};
struct node
{
int x,y;
int step;
} e,ne;
queue<node>q;
int maxn;
int bfs()
{
maxn=INF;
int ans=0;
while(!q.empty())
{
q.pop();
}
q.push(e);
memset(vis,-1,sizeof(vis));
vis[e.x][e.y]=0;
while(!q.empty())
{
if(q.front().step<maxn)
{
for(int i=0; i<4; i++)
{
int x=q.front().x+D[i][0];
int y=q.front().y+D[i][1];
int step=q.front().step+1;
if(0<=x&&x<n&&0<=y&&y<m&&vis[x][y]&&mapp[x][y]!='T')
{
if(mapp[x][y]=='S')
{
maxn=step;
}
else
{
ans+=mapp[x][y]-'0';
}
ne.x=x;
ne.y=y;
ne.step=step;
vis[x][y]=0;
q.push(ne);
}
}
}
q.pop();
}
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0; i<n; i++)
{
scanf("%s",mapp[i]);
}
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
if(mapp[i][j]=='E')
{
e.x=i;
e.y=j;
e.step=0;
}
}
}
printf("%d\n",bfs());
}
return 0;
}
影象旋轉
輸入後輸出。
#include<algorithm>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int main()
{
int a[105][105];
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
scanf("%d",&a[i][j]);
}
}
for(int i=0; i<m; i++)
{
for(int j=n-1; j>=0; j--)
{
printf(j?"%d ":"%d\n",a[j][i]);
}
}
}
return 0;
}
連續出現的字元
遍歷字元計算連續出現的長度。
#include<algorithm>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int n, m;
char a[1000];
int main()
{
while (cin >> n)
{
cin >> a;
int len = strlen(a);
int l = 0;
bool flag = false;
for (int i = 0; i<=len;)
{
if (a[i] == a[l])
{
i++;
}
else
{
if (i - l >= n)
{
flag = true;
break;
}
else
{
l = i;
}
}
}
if (flag)
{
printf("%c\n", a[l]);
}
else
{
printf("No\n");
}
}
return 0;
}
正方形面積
輸入後輸出平方。
#include<algorithm>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int n;
int main()
{
while(scanf("%d",&n)!=EOF)
{
printf("%d\n",n*n);
}
return 0;
}