CUGBACM Codeforces Tranning 1 解题报告
来源:互联网 发布:飞鹰网络电视直播tv版 编辑:程序博客网 时间:2024/05/29 04:48
比赛链接:点击打开链接
自己太弱,只A了第一题。。。。。。
A题 水到没朋友。。。。
AC代码:
#include<iostream>#include<string>#include<cstring>#include<cstdio>#include<cmath>#include<iomanip>#include<map>#include<queue>#include<set>#define pi acos(-1.0)#define eps 1e-8typedef long long ll;using namespace std;int mi[50],mx[50],ans[50];int d,sum;int main(){ int i; scanf("%d%d",&d,&sum); int mi_sum=0,mx_sum=0; for(i=0; i<d; i++) { scanf("%d%d",&mi[i],&mx[i]); mi_sum+=mi[i],mx_sum+=mx[i]; } if(sum<=mx_sum && sum>=mi_sum) { printf("YES\n"); int rest = sum-mi_sum; for(i=0; i<d; i++) ans[i]=mi[i]; for(i=0;i<d;i++) { if(rest ==0 ) break; int tmp=mx[i]-mi[i]; if(rest>=tmp) { ans[i]=mx[i]; rest-=tmp; } else if(rest< tmp) { //if(ans[i]) ans[i]=mi[i] + rest; rest=0; } } for(i=0; i<d; i++) { printf("%d ",ans[i]); } printf("\n"); } else printf("NO\n"); return 0;}
B题 dp
读题的时候竟然忽略了只能向下或者向右走这个关键一步!!!!!!所以一开始想成dfs了。。。然后正好看到学长们这道题尝试了几次T了,就更加坚信这一错误观点了。。。(他们T的原因是数组元素中有0的情况没有考虑到)。后来发现了,但是一方面时间不够,另一方面对路径的记录有些凌乱。所以。。。你懂的。
这题实际上就是一道棋盘dp。求路径上的数相乘乘积3结果末尾0的个数最少。因为零由2*5得到。所以对于棋盘上的每一个数,要记录它包含多少个2和5。
动态转移方程为:dp[i][j]=min(dp[i][j-1],dp[i-1][j])。result=min(dp[n-1][n-1][0],dp[n-1][n-1][1])。这道题的trick在于棋盘上的数有可能为0。如果不特判,必然T。
另一个需要强化的就是路径的记录。开一个二维数组记录路径,最后将 符合的路径存放在一个一维数组中输出。
AC代码
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<iomanip>#include<algorithm>#include<cmath>#include<queue>#include<map>#include<vector>#include<set>#include<stack>typedef long long ll;#define pi acos(-1)#define eps 1e-6;using namespace std;const int inf=1<<28;const int maxn=105;int mp[1050][1050],dp[1050][1050][2],has_zero,zero_x,zero_y;///dp[0]表示5,dp[1]表示2;char dir[1050][1050][2];char way[3050];void get_cnt(int num,int i,int j){ while(num % 5== 0 && num) { dp[i][j][0]++; num/=5; } while(num % 2 ==0 && num) { dp[i][j][1] ++ ; num/=2; }}int main(){ int n,i,j; memset(dp,0,sizeof(dp)); has_zero=0; scanf("%d",&n); for(i=0; i<n; i++) { for(j=0; j<n; j++) { scanf("%d",&mp[i][j]); if(mp[i][j]== 0) { has_zero=1; zero_x=i,zero_y=j; dp[i][j][0] = dp[i][j][1] = 1; } else get_cnt(mp[i][j],i,j); } } for(i=0; i<n; i++) { for(j=0; j<n; j++) { for (int k = 0; k < 2; k++) { if (i == 0 && j == 0) continue; if (i == 0) { dp[i][j][k] += dp[i][j-1][k]; dir[i][j][k] = 'R'; } else if (j == 0) { dp[i][j][k] += dp[i-1][j][k]; dir[i][j][k] = 'D'; } else { dp[i][j][k] += dp[i-1][j][k] < dp[i][j-1][k] ? dp[i-1][j][k] : dp[i][j-1][k]; dir[i][j][k] = dp[i-1][j][k] < dp[i][j-1][k] ? 'D' : 'R'; } } } } if(min(dp[n-1][n-1][0],dp[n-1][n-1][1])>1 && has_zero) { printf("1\n"); for (int i = 0; i < zero_x; i++) printf("D"); for (int i = 0; i < n-1; i++) printf("R"); for (int i = zero_x; i < n-1; i++) printf("D"); } else { printf("%d\n",min(dp[n-1][n-1][0],dp[n-1][n-1][1])); int k=1; if(dp[n-1][n-1][0] < dp[n-1][n-1][1]) k=0; int cnt=0; int i=n-1,j=n-1; while(i!=0 || j!=0) { way[cnt++]= dir[i][j][k]; if(dir[i][j][k]=='R') j--; else if(dir[i][j][k]=='D') i--; } for(i=cnt-1; i>=0; i--) putchar(way[i]); } puts(""); return 0;}
C题 一道模拟题 和五子棋差不多,变成了三子棋。难点在于要判断的情况太多了,其中,平局情况只有在两种棋子相加恰好等于9即无法再放棋子的时候,而不是无论如何放都不可能有一方赢的时候,这一点我考虑错了,所以一直在想怎么判断在棋子没填满的情况下判断是否是平局,显然是画蛇添足了。另外,我在做题的时候,判断太复杂,代码量很大,比赛结束后看了琦神代码才恍然大悟,我太弱了。
AC代码
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<iomanip>#include<algorithm>#include<cmath>#include<queue>#include<map>#include<vector>#include<set>#include<stack>typedef long long ll;#define pi acos(-1)#define eps 1e-6using namespace std;const int inf=1<<28;const int maxn=105;char mp[4][4];int x_cnt,zero_cnt;int win(int t){ char c; int i,j; if(t==0) c='X'; else c='0'; int cnt=0; for(i=0; i<3; i++) { cnt=0; for(j=0; j<3; j++) { if(mp[i][j]==c) cnt++; } if(cnt==3) return 1; } cnt=0; for(j=0; j<3; j++) { cnt=0; for(i=0; i<3; i++) { if(mp[i][j]==c) cnt++; } if(cnt==3) return 1; } cnt=0; for(i=0; i<3; i++) { if(mp[i][i] == c) cnt++; if(cnt==3) return 1; } cnt=0; for(i=0; i<3; i++) { if(mp[i][2-i]==c) cnt++; if(cnt==3) return 1; } return 0;}int check(){ int a=win(0); int b=win(1);//puts("xxxxx"); if(a==1 && b==1) return 0;///0 illegal if(a==1 && x_cnt==zero_cnt) { return 0; } if(b==1 && x_cnt==zero_cnt+1) return 0; if(a==1) return 1;///first win; if(b==1) return 2; ///second win if(x_cnt+zero_cnt == 9) return 3; ///draw if(x_cnt==zero_cnt) return 4; ///first if(x_cnt==zero_cnt+1) return 5;///second}int main(){ int i,j; x_cnt=0,zero_cnt=0; for(i=0; i<3; i++) { scanf("%s",mp[i]); } for(i=0; i<3; i++) { for(j=0; j<3; j++) { if(mp[i][j] == 'X') x_cnt++; else if(mp[i][j] == '0') zero_cnt++; } } int ans= check(); if((x_cnt>zero_cnt+1) || (x_cnt<zero_cnt)) printf("illegal\n"); else if(ans==0) printf("illegal\n"); else if(ans==1) printf("the first player won\n"); else if(ans==2) printf("the second player won\n"); else if(ans==3) printf("draw\n"); else if(ans==4) printf("first\n"); else if(ans==5) printf("second\n"); return 0;}
D题
给定正多边形三点,求符合条件的面积最小的正多边形面积。
一道几何题。因为时间不够了,比赛时没有看。通过给定三点求出三角形三边长,根据余弦定理,求得三个角大小,根据正弦定理a/sin(A)=2r进而求得外接圆半径。求三角形三角所对应的圆心角x,y,z。若正n边形满足条件,则设t=2*pi/n,则x y z都应是t的整数倍,并且 x/t + y/t + z/t == n 。其面积为0.5*r*r*sin(t)*n。
AC代码
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<iomanip>#include<algorithm>#include<cmath>#include<queue>#include<map>#include<vector>#include<set>#include<stack>typedef long long ll;#define pi acos(-1.0)#define eps 1e-6using namespace std;const int inf=1<<28;const int maxn=105;double x[5],y[5];double edge[5];double sita[5];double r,per_sita;void get_edge(){ edge[0]= sqrt((x[0]-x[1])*(x[0]-x[1]) + (y[0]-y[1]) * (y[0]-y[1])); edge[1]= sqrt((x[0]-x[2])*(x[0]-x[2]) + (y[0]-y[2]) * (y[0]-y[2])); edge[2]= sqrt((x[1]-x[2])*(x[1]-x[2]) + (y[1]-y[2]) * (y[1]-y[2]));}void get_sita(){ sita[0] = acos((edge[1]*edge[1]+edge[2]*edge[2]-edge[0]*edge[0])/(2*edge[1]*edge[2])); sita[1] = acos((edge[0]*edge[0]+edge[2]*edge[2]-edge[1]*edge[1])/(2*edge[0]*edge[2])); sita[2] = acos((edge[1]*edge[1]+edge[0]*edge[0]-edge[2]*edge[2])/(2*edge[1]*edge[0])); // cout<<sita[0]<<" "<<sita[1]<<" "<<sita[2]<<" "<<sita[0]+sita[1]+sita[2]<<"\n";}bool check(int n){ int sum=0; for(int i=0; i<3; i++) { sum+=int((sita[i]+eps) / per_sita); } if(fabs(sum*per_sita-2*pi)<=eps) return true; return false;}int main(){ int i; for(i=0; i<3; i++) { scanf("%lf%lf",&x[i],&y[i]); } get_edge(); get_sita(); r=edge[0]/sin(sita[0])/2;///求外接圆半径 for(i=0;i<3;i++) sita[i] *=2; for(i=3; i<=100; i++) { per_sita = 2*pi / i; if(check(i)) { break; } } double s = 0.5*r*r *sin(per_sita)*i; printf("%.10lf\n",s); return 0;}
E题
给一个字符串,只由“(”,“)”和“?”组成.。问号处可填“(”或“)”。并给定使用左右括号所需的cost。求cost最小的匹配括号串。对于当前串,只要左括号的个数大于右括号就可以继续。如果不符合,就要将之前?处改为左括号。根据贪心思想,使用的?必然是a-b最小的那个,所以可以使用一个优先队列来实现。串访问完后,只要判断左括号的数量是否为0即可。
AC代码
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<iomanip>#include<algorithm>#include<cmath>#include<queue>#include<map>#include<vector>#include<set>#include<stack>typedef long long ll;#define pi acos(-1)#define eps 1e-6using namespace std;const int inf=1<<28;const int maxn=55005;struct node{ int w,id; node (int x,int y) :w(x),id(y) {} ; bool friend operator <(node a,node b) { return a.w>b.w; }};priority_queue <node > q;char s[maxn];int main(){ scanf("%s",s); int n=strlen(s),a,b,i; int rest = 0; ll cost=0; for(i=0; i<n; i++) { if(s[i]=='(') rest++; else if(s[i]==')') rest--; else if(s[i]=='?') { s[i]=')'; scanf("%d%d",&a,&b); cost+=b; q.push(node(a-b,i)); rest--; } if(rest<0) { if(q.empty()) { break; } else { node tmp=q.top(); q.pop(); s[tmp.id]='('; cost+=tmp.w; rest+=2; } } } if(rest) printf("-1\n"); else printf("%lld\n%s\n",cost,s); return 0;}
- CUGBACM Codeforces Tranning 1 解题报告
- CUGBACM Codeforces Tranning 1 解题报告
- CUGBACM Codeforces Tranning 1 解题报告
- CUGBACM Codeforces Tranning 2 解题报告
- CUGBACM Codeforces Tranning 2 解题报告
- CUGBACM Codeforces Tranning 3 解题报告
- CUGBACM Codeforces Tranning 3 解题报告
- CUGBACM Codeforces Tranning 5解题报告
- CUGBACM Codeforces Tranning 8解题报告
- CUGBACM Codeforces Tranning 1 题解
- CUGBACM Codeforces Tranning 2 题解
- CUGBACM Codeforces Tranning 3 题解
- codeforces 1A 解题报告
- codeforces 1B 解题报告
- Codeforces Round #250 (Div.1) 解题报告
- CodeForces解题报告——1
- Codeforces Round #327 (Div. 1) 解题报告
- Codeforces Round #326 (Div. 1) 解题报告
- 站点排名从业者如何合理设置装备摆设有限的资源
- 实验室第七周周工作总结
- 如何在structs2中使用servlet
- D3D11学习(头文件及D3D库)
- 面试题7 用两个栈实现队列
- CUGBACM Codeforces Tranning 1 解题报告
- 单选框,复选框的多选使用问题
- 数据结构图篇(自己容易理解有误的地方)
- C#解析XML文件
- Free命令每个数字的含义 和 cache 、buffer的区别
- Check the difficulty of problems - POJ 2151 概率dp
- spring国际化支持
- 给控件添加图片
- java web servlet/filter/listener/interceptor区别与联系