2017新成员基础练习
A - FatMouse' Trade
该题就是,简单的一个贪心的问题,求最大金额的数目,只需要sort排序就可以了。
代码如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; struct node { int m; int n; }; bool cmp(node n,node m) { return n.n*1.0/n.m>m.n*1.0/m.m; } struct node a[1010]; int n; int m; int main() { while(scanf("%d%d",&n,&m)!=EOF) { if(n<0 && m<0) break; for(int i=0;i<m;i++) { scanf("%d%d",&a[i].n,&a[i].m); } sort(a,a+m,cmp); double sum = 0; for(int i=0;i<m;i++){ if(n>=a[i].m){ n = n-a[i].m; sum+=a[i].n; }else{ sum+=n*(a[i].n*1.0/a[i].m); break; } } printf("%.3f\n",sum); } return 0; }
B - Fire Net
该题求放炮塔,最多能放多少个?炮塔四面都可以开炮,所以不能面对着炮塔。如果有中间应该有一个墙、去阻隔它的炮弹。采用广度优先搜索(DFS)。
代码如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; char map[10][10]; int n,xx,yy; int flag=0; int ans=0; //判断是不是可以放 bool cmp(int x,int y) { for(int i=x-1;i>=1;i--) { if(map[i][y]=='#') return false; if(map[i][y]=='X') break; } for(int i=y-1;i>=1;i--) { if(map[x][i]=='#') return false; if(map[x][i]=='X') break; } return true; } //递归寻找 int DFS(int x,int y,int z) { if(y==n+1){ x++; y=1; } if(x==n+1 && y==1) { // print(); if(ans < z) ans = z; return z; } if(flag) return z; if(map[x][y]=='.' && cmp(x,y)) { map[x][y]='#'; DFS(x,y+1,z+1); map[x][y]= '.'; } DFS(x,y+1,z); } int main() { while(scanf("%d",&n),n) { ans=0; xx = yy =1; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { cin>>map[i][j]; } } DFS(xx,yy,0); printf("%d\n",ans); } return 0; }
C - Climbing Worm
该题指的是爬虫爬墙的问题,每天爬一点,之后又会掉下去一点,每一次要一分钟。求至少多少分钟爬到井口。
注意在第一次爬,和最后一次的爬,就可以了。
代码如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int main() { int x,y,z; while(scanf("%d%d%d",&x,&y,&z)!=EOF) { if(x==y && y==z && y==0) break; int score = 0; while(true){ if(score!=0){ x+=z; x-=y; score+=2; }else{ x-=y; score++; } if(x<=0) break; } printf("%d\n",score); } return 0; }
D - Moving Tables
该题讲的是搬房子,在某一个人搬房子的时候,他所占用的街道,别人是不能用的。我们主要注意在像2 3,从2搬3的这样的数据的时候,前者为偶数,或者后者为奇数的时候,他们所占用的街道范围,其实是偶数-1,或者奇数加一,的范围。如上面的2到3,其实可以看做1到4都被占用了。只要在数据输入的时候,改变一下就可以了。还有数据可能前者大于后者,例如3到2.指从3搬到2.
从而该题变成了求范围的类型的题目。
///该代码,主要是先求可以一起搬的房子,无冲突的, ///之后求有冲突的,也就是自己在搬的时候,别人不能搬的那种, #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; struct app{ int kai; int jie; int k; }a[401]; bool cmp(app a,app b) { if(a.kai!=b.kai) return a.kai<b.kai; return a.jie<b.jie; } int main() { int n,m; scanf("%d",&n); while(n--) { memset(a,0,sizeof(a)); scanf("%d",&m); for(int i=0;i<m;i++) { scanf("%d%d",&a[i].kai,&a[i].jie); if(a[i].kai%2==0) a[i].kai--; if(a[i].jie%2!=0) a[i].jie++; if(a[i].kai>a[i].jie) swap(a[i].kai,a[i].jie); } sort(a,a+m,cmp); int ans =0; for(int i=0;i<m;i++) { if(a[i].k==1) continue; int max = a[i].kai; int min = a[i].jie; int q = 0; for(int j=i+1;j<m;j++) { if( (min<a[j].kai || max>a[j].jie) && a[j].k==0) { max = a[j].kai; min = a[j].jie; a[j].k = 1; if(q==0) { ans+=10; //他们可以一起搬,就记录时间10分钟。 a[i].k=1; q=1; } } } } for(int i=0;i<m;i++) { if(a[i].k==0){ ans+=10; //他们只能自己搬,不能和别人一起搬的。 } } printf("%d\n",ans); } return 0; }
E - Wooden Sticks
该题就是讲加工木头的问题,突破点就是在:看一组数据, n1,m1,n2,m2,如果n1<=n2&&m1<=m2他们可以一起加工,时间为单个加工时间。所以我们只要排序一下,按照n1从小到大,n1相等,m1也从小到大的顺序排序就可以了。
///该代码,主要是先求可以一起加工的木头 ///之后自己在加工的时候,别人不能和你一起加工的那种, #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; struct node { int n,m,k; }a[10005]; bool cmp(node n,node m) { if(n.n!=m.n) { return n.n<m.n; } return n.m<m.m; } int main() { int n; int m; scanf("%d",&n); while(n--) { scanf("%d",&m); memset(a,0,sizeof(a)); for(int i=0;i<m;i++) { scanf("%d%d",&a[i].n,&a[i].m); } sort(a,a+m,cmp); int ans =0; for(int i=0;i<m;i++) { if(a[i].k==1) continue; int max = a[i].n; int min = a[i].m; int q = 0; for(int j=i+1;j<m;j++) { if(max<=a[j].n && min<=a[j].m && a[j].k==0) { max = a[j].n; min = a[j].m; a[j].k = 1; if(q==0) { ans++; a[i].k=1; q=1; } } } } for(int i=0;i<m;i++) { if(a[i].k==0){ ans++; } } printf("%d\n",ans); } return 0; }
F - Tian Ji -- The Horse Racing
该题,就是田忌赛马,我们知道一点就可以了,无论怎么样我们都要用最不好的马,去减少国王最好的马,即使最不好的马之间相同,我们也要减少国王最好的马,除非田忌赢了,否则不好的马,就去抵消国王最好的马,最好的马比不过我们也去减少最不好的马,从而抵消掉。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int main() { int a[1000]; int n; int b[1000]; int i,s,j,e,sum; while(scanf("%d",&n)!=EOF) { if(n==0) break; for( i=0; i<n; i++) scanf("%d",&a[i]); for( i=0; i<n; i++) scanf("%d",&b[i]); sort(a,a+n); sort(b,b+n); i=s=0; j=e=n-1; sum=0; while(i<=j) { if(a[i]>b[s]) { sum++; s++; i++; } else if(a[i]<b[s]) { sum--; e--; i++; } else { if(a[j]>b[e]) { sum++; e--; j--; } else { if(a[i]<b[e]) sum--; e--; i++; } } } printf("%d\n",sum*200); } return 0; }
G - 最少拦截系统
该题,就是把导弹拦截下来,用最少的系统数目,我们用一个数组去存每一个拦截系统的下限。如果你低于下限,那么你就被拦截,不然就加一个系统。就可以了。把之前的遍历一边就ok了。
代码如下:
#include <iostream> #include <string.h> using namespace std; int dao[1004]; int main() { int n; int height; int i,j; while(cin>>n) { memset(dao,0,sizeof(dao)); int num=1; cin>>dao[1]; for(i=2;i<=n;i++) { cin>>height; for(j=1;j<=i;j++) { if(height<=dao[j]) { dao[j]=height; break; } } if(j>i) ///需要加一个系统区拦截。 dao[num++]=height; } cout<<num<<endl; } return 0; }
H - Flying to the Mars
就是求相同非负整数出现的最多数目,你用一个int数组去存起来就可以了,可以去做,也可以用一个map去做也就。
代码如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<map> using namespace std; int main() { int n; while(scanf("%d",&n)!=EOF) { int s; map<int,int>a; a.clear(); int max =0; for(int i=0;i<n;i++) { scanf("%d",&s); a[s]++; if(a[s]>max) max = a[s]; } printf("%d\n",max); } return 0; }
I - 今年暑假不AC
该题就是求能看完整节目的数目。简单的贪心思想。
代码如下:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; struct node { int x,y; }a[10010]; bool cmp(node n,node m) { return n.y<m.y; } int main(){ int n; while(scanf("%d",&n),n) { for(int i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].y); sort(a,a+n,cmp); int kai = 0; int jie = 0; for(int i=0;i<n;i++) { if(kai<=a[i].x) { kai = a[i].y; jie++; } } printf("%d\n",jie); } return 0; }
J - 多项式求和
水题。
代码如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int main() { int n; while(scanf("%d",&n)!=EOF) { int m; for(int j=0;j<n;j++){ scanf("%d",&m); double sum = 0; for(int i=1;i<=m;i++) { if(i%2==0) sum-=1.0/i; else sum+=1.0/i; } printf("%.2f\n",sum); } } return 0; }
K - Repair the Wall
水题。
代码如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; bool cmp(int n,int m) { return n>m; } int k[600]; int main(){ int n,m; double sum ; int q = 0; while(scanf("%d%d",&n,&m)!=EOF) { q=0; sum =0; memset(k,0,sizeof(k)); for(int i=0;i<m;i++) scanf("%d",&k[i]); sort(k,k+m,cmp); for(int i=0;i<m && q==0;i++) { sum+=k[i]; if(sum>=n) { printf("%d\n",i+1); q=1; } } if(q==0) printf("impossible\n"); } return 0; }L - 悼念512汶川大地震遇难同胞——老人是真饿了
详细解答:http://blog.csdn.net/zjwsa/article/details/74941097
代码如下:
#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<cstring> using namespace std; struct node { int x,y; }a[10005]; bool cmp(node n,node m) { return n.x<m.x; } int main() { int n; int i,j,k,t; scanf("%d",&n); int sum,num; while(n--) { double q = 0; memset(a,0,sizeof(a)); scanf("%d%d",&sum,&num); for(i=0;i<num;i++) scanf("%d%d",&a[i].x,&a[i].y); sort(a,a+num,cmp); for(i=0;i<num;i++) { if(sum>=a[i].x*a[i].y) { sum = sum - a[i].x*a[i].y; q+=a[i].y; }else{ q+=sum*1.0/a[i].x; sum=-1; } if(sum<=0) break; } printf("%.2f\n",q); } return 0; }
M - Filthy Rich
该题,讲的是从开始点到最后一点,你选择一条路径可以拿到最多的黄金。你只可以选择前进,下走,斜走。不可以后退,求最多的黄金数目。简单的动态规划,
代码如下:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; int map[1005][1005]; int dp[1005]; int x,y; int main() { int n; scanf("%d",&n); int t=1; while(n--) { scanf("%d%d",&x,&y); memset(map,0,sizeof(map)); memset(dp,0,sizeof(dp)); for(int i=1;i<=x;i++) { for(int j=1;j<=y;j++) { scanf("%d",&map[i][j]); } } for(int i=1;i<=x;i++) { for(int j=1;j<=y;j++) { if(i==1) dp[j] = dp[j-1] + map[i][j]; else{ int max = dp[j-1]>dp[j]?dp[j-1]:dp[j]; dp[j] = max + map[i][j]; } } } printf("Scenario #%d:\n",t++); printf("%d\n\n",dp[y]); } return 0; }
N - 迷瘴
简单排序一下,就可以了。用一个变量去判断存了一件物品的浓度和要求浓度比较,可以就存起来,存起来的数目加加,否则直接退出,因为后面的浓度比你更大,所以后面也就不需要加了。
代码如下:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; int a[105]; int main() { int n,z,v,w,i; scanf("%d",&n); while(n--){ scanf("%d%d%d",&z,&v,&w); double sum; for(i=0;i<z;i++) scanf("%d",&a[i]); sort(a,a+z); if(a[0]>w){ printf("0 0.00\n"); }else{ sum=0; double t; int k=0; for(i=0;i<z;i++) { sum+=a[i]; /// 加入你这种物品的浓度和要求浓度比较, if(sum*1.0/(i+1)>w){ break; }else{ t=sum; } ///加入的物品数目。 k++; } printf("%d %.2f\n",k*v,t*1.0/k/100); } } return 0; }
O - Buy the Ticket
有时间,有思路再去写一下。主要就是太麻烦了。有时间就来更新一下。
P - Tri Tiling
该题,是一个递推公式,就是说,当他是奇数的时候,他是填不满的,因为会剩下一个1*1的方格。不信的话,你可以去试试,在此一点坑,0的时候是1.
代码如下:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; int main() { int n; int a[31]; a[0] = 1; a[1] = 0; a[2] = 3; a[3] = 0; a[4] = 11; for(int i=5;i<=30;i++) { a[i] = a[i-2]*4-a[i-4]; } while(scanf("%d",&n)!=EOF) { if(n==-1) break; if(n%2!=0) printf("0\n"); else{ printf("%d\n",a[n]); } } return 0; }
Q - 三角形
也是一个公式,因为一条边可以把区域分成2部分,而如果两条边相交于一点,就会把区域分成4个部分。两个三角形,一边相交就是4,也就是多产生了两条边,三角形有3条边,那就是用原来的加上多产生的,2+2*3就是8了。再去推理3个三角形,一边就是8,原来是4,多产生了4个。每一条边多产生4,三条边就是12.那也就是原来的8加上现在多产生的12,等于20.等等,我们再于几个三角形,挂上钩,因为我们是要得到一个递推公式,毕竟是电脑在处理。
1 2
2 8
3 20
拆一下,推来的公式,1的时候,为2,2的时候为2*3+2,3的时候为8+4*3,与n挂上钩就是。
所以我们就得出一个公式 a[i] = a[i-1]+2*3*(i-1);公式就是这样的,不信你们可以去推一下其他的a[i]去试一下,检验一下就可以了。
代码如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int main() { int a[10001]; a[1] = 2; for(int i=2;i<10001;i++) { a[i] = a[i-1]+6*(i-1); } int n; scanf("%d",&n); while(n--) { int m; scanf("%d",&m); printf("%d\n",a[m]); } return 0; }
R - Let the Balloon Rise
该题,大意就是求相同颜色的最多的数量的那种颜色。解决就是采用一个map,就可以了。
#include <iostream> #include <stdio.h> #include <string.h> #include <map> #include <string> using namespace std; int main() { string a,maxt; map<string,int>s; int n; while(~scanf("%d",&n),n) { int max=0; for(int i=0;i<n;i++) { cin>>a; s[a]++; if(max<s[a]) { max=s[a]; maxt=a; } } cout<<maxt<<endl; } return 0; }
S - Number Sequence
该题,只要找出规律就可以了。由于它是以1和1开始的,所以我们只要找到那个连续的数字是1和1.就可以了
代码如下:
#include <stdio.h> #include <string.h> int s[50]; int main() { int a,b,n,i; while(scanf("%d%d%d",&a,&b,&n),a || b || n) { int i; s[0]=s[1]=1; for(i = 2; i<50;i++) { s[i] = (a*s[i-1]+b*s[i-2])%7; if(s[i] ==1 && s[i-1] == 1) {break;} } n = n%(i-1); if(n == 0) printf("%d\n",s[i-2]); else printf("%d\n",s[n-1]); } return 0; }
T - Elevator
详细解释,在此:http://blog.csdn.net/zjwsa/article/details/74910194
大致意思就是电梯,停止时间不算。只算一层位置到一层位置之间的时间。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int main() { int n; int a[100]; while(scanf("%d",&n)!=EOF) { if(n==0) break; memset(a,0,sizeof(a)); a[0] = 0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } int time = 0; for(int i=1;i<=n;i++) { if(a[i]-a[i-1]>0) { time +=(a[i]-a[i-1])*6+5; } else { time +=(a[i-1]-a[i])*4+5; } } printf("%d\n",time); } return 0; }
U - u Calculate e
该题就是输出各种的情况,就可以了。
代码如下:
#include<iostream> #include<cstdio> using namespace std; int main() { printf("n e\n- -----------\n"); int k = 1,i,j; double e= 0; for(i = 0;i < 10;i ++) { k = 1; for(j = 1; j <= i; j ++) k *= j; e += (double)1/k; if(i <= 1) printf("%d %.0f\n",i,e); else if(i == 2) printf("%d %.1f\n",i,e); else printf("%d %.9f\n",i,e); } }
V - Digital Roots
该题,很水,把数字每一位求和就可以了。注意就是第一次求和,还可能大于10.所以我们就不断的考虑,是不是小于10.
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int ans(int sum1) { int sum=0; while(sum1>0) { int t = sum1%10; sum+=t; sum1 = sum1/10; } return sum; } int main() { char a[10005]; while(gets(a)!=NULL) { if(strlen(a)==1 && a[0]=='0') break; int sum=0; for(int i=0;i<strlen(a);i++){ sum+=a[i]-'0'; } while(sum>=10) { sum = ans(sum); } cout<<sum<<endl; } return 0; }
W - Uniform Generator
该题,就是求他按照那个公式不断求值,之后就是看重复了没,如果重复了,就退出。计算从开始到现在重复的数字之间出现了多少个数字。
代码如下:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; int f[100005]; int main() { int n,m; int time; while(scanf("%d%d",&n,&m)!=EOF) { memset(f,0,sizeof(f)); int sum = 0; int q=0; for(int i=0;i<m;i++) { sum = (sum+n)%m; if(f[sum]==1) break; else f[sum]=1; } time=0; for(int i=0;i<m;i++) { if(f[i]==1) time++; } if(time==m) printf("%10d%10d Good Choice\n\n",n,m); else printf("%10d%10d Bad Choice\n\n",n,m); } return 0; }
X - A Mathematical Curiosity
该题,就是求满足公式的个数。
代码如下:
#include<iostream> #include<cstdio> using namespace std; int main() { int n,m; int t; scanf("%d",&t); while(t--) { int o = 1; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0 && m==0 ) break; int ti = 0; for(int i=1;i<n;i++) { for(int j=i+1;j<n;j++) { if((i*i+j*j+m)%(i*j)==0) { ti++; } } } printf("Case %d: %d\n",o++,ti); } if(t!=0){ cout<<endl; } } return 0; }
Y - Fibonacci Again
该题,主要就是找规律,就可以了。你可以去找1到80之间能被3整除的数字,找出规律,就是直接判断这个数字满不满足这个规律。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int a[2]; int main() { int n; a[0]=1; a[1]=1; while(scanf("%d",&n)!=EOF) { int sum; if(n<2){ sum = a[n]; }else{ sum = (n-2)%4; } if(!sum){ printf("yes\n"); }else{ printf("no\n"); } } return 0; }
Z - Ignatius and the Princess III
这题,没有思路。等我有时间了,再去看看,然后更新一下。