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;}


0 0
原创粉丝点击