打砖块

题目链接:http://acm.ocrosoft.com/problem.php?cid=1629&pid=51

题目描述:

小红很喜欢玩一个叫打砖块的游戏,这个游戏的规则如下:
        在刚开始的时候,有n行*m列的砖块,小红有k发子弹。小红每次可以用一发子弹,打碎某一列当前处于这一列最下面的那块砖,并且得到相应的得分。
        如图所示:

 

http://acm.ocrosoft.com/upload/pimg6936_1.jpg

 某些砖块在打碎以后,还可能将得到一发子弹的奖励。最后当所有的砖块都打碎了,或者小红没有子弹了,游戏结束。
        小红在游戏开始之前,就已经知道每一块砖在打碎以后的得分,并且知道能不能得到一发奖励的子弹。小红想知道在这次游戏中她可能的最大得分,可是这个问题对于她来说太难了,你能帮帮她吗?

输入

第一行有3个正整数,n,m,k。表示开始的时候,有n行*m列的砖块,小红有k发子弹。
        接下来有n行,每行的格式如下:
        f1 c1 f2 c2 f3 c3 …… fm cm
        其中fi为正整数,表示这一行的第i列的砖,在打碎以后的得分。ci为一个字符,只有两种可能,Y或者N。Y表示有一发奖励的子弹,N表示没有。

 

所有的数与字符之间用一个空格隔开,行末没有多余的空格。

对于20%的数据,满足1<=n,m<=5,1<=k<=10,所有的字符c都为N
对于50%的数据,满足1<=n,m<=200,1<=k<=200,所有的字符c都为N

对于100%的数据,满足1<=n,m<=200,1<=k<=200,字符c可能为Y
对于100%的数据,所有的f值满足1<=f<=10000

 

输出

仅一个正整数,表示最大的得分。

样例输入

3 4 2
9 N 5 N 1 N 8 N
5 N 5 Y 5 N 5 N
6 N 2 N 4 N 3 N

样例输出

13

思路:先将输入的数据预处理,先求出每一列用ans颗子弹来打j列所能得到的最打分数,最后再用三层循环得出m行k颗子弹所能得到的最大分数。这里有一个坑点,碰到能加子弹的砖块时,你不一定能直接不加子弹直接加砖块的分数,如果你只有三颗子弹,加次数的砖块在第四个时,你就不能直接加第四块砖块的分数,所以就需要在代码中分两种情况处理。

 

代码:

#include<stdio.h>
int max(int x,int y)
{
    if(x>y)
        return x;
    else
        return y;
}
int main()
{
    int n,m,k;
    int score[205][205]={0};
    int bullet[205][205]={0};
    int dp[205][205]={0},dpy[205][205]={0};
    int f[205][205]={0},fy[205][205]={0};
    char t;
    //输入
    scanf("%d %d %d",&n,&m,&k);
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            scanf("%d %c",&score[i][j],&t);
            if(t=='N')
                bullet[i][j]=0;
            else
                bullet[i][j]=1;
        }
    }
    //预处理,将第j列用不同数量的子弹所能获得分数的情况列出来
    for(int j = 1; j <= m; j++)
    {
        //所用的子弹数量,每一列都置0
        int ans = 0;
        for(int i = n; i>0; i--)
        {
            //当前砖块打了能加子弹,相当于不用子弹直接得分
            if(bullet[i][j])
                dp[j][ans]+=score[i][j];
            //不能加子弹,相当于用了一颗子弹,所以ans++
            else
            {
                ans++;
                //在没打子弹的基础上加上这轮打掉的砖块的分数
                dp[j][ans] = dp[j][ans-1] + score[i][j];
                dpy[j][ans] = dp[j][ans-1] + score[i][j];
            }
        }
    }
    for(int i = 1; i <= m; i++)
    {
        for(int j = 0; j <= k; j++)
        {
            for(int gg = 0;gg <= j&& gg <= n; gg++)
            {
                f[i][j]=max(f[i][j],f[i-1][j-gg]+dp[i][gg]);
                if(gg != 0)
                    fy[i][j] = max(fy[i][j], f[i-1][j-gg] + dpy[i][gg]);// 后打当前列
                if(j - gg > 0)
                    fy[i][j] = max(fy[i][j], fy[i-1][j-gg] + dp[i][gg]);//先打当前列
            }
        }
    }
    printf("%d\n",fy[m][k]);
    return 0;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TC编写 main() { int mode=VGAHI,driver=VGA; char ch; unsigned int l; int i,gi,gj,j,flag=1;/*i,j是循环变量,flag是标记变量,-1:向x负半轴移动,+1:向x正半轴移动*/ double qx,qy,k,b=0.0,speech=0.4,x,y; double r=2.0,bx=60.0,byy=270.0; double pianx=100.0,piany=100.0,tx=20.0,ty=10.0,jx=2.0,jy=2.0; int mx=0,my=0,mb,sum;/*sum纪录砖块的数目*/ FILE * p; if((p = fopen("record.dat", "r")) == NULL) { p=fopen("record.dat","w"); fprintf(p,"0 0 0 0 0\n"); rewind(p); } fclose(p); initgraph(&driver,&mode,"C:\\tc"); setbkcolor(BLUE); Msinit(); Setmouse((int)(pianx+1+bx/2),(int)((tx+jx)*8+pianx-1-bx/2),(int)byy+piany,(int)byy+piany); star: cleardevice();/*程序重载的介入点*/ setcolor(RED); outtextxy(30,20,"^_^ Welcome to Play Hitting Brick Game! ^_^"); sum=0; qx=100.0+pianx-10;qy=180.0+pianx-10;k=0.33; setcolor(7); rectangle((int)(pianx-2),(int)(piany-2),(int)((tx+jx)*8+2+pianx),302+piany); setcolor(1); rectangle((int)(pianx-1),(int)(piany-1),(int)((tx+jx)*8+1+pianx),301+piany); /*读取盘面情况*/ p=fopen("record.dat", "r"); for(i=0;i<5;i++) fscanf(p,"%x ",&zhuan[i]); fclose(p); /*画砖块*/ for(i=0;i<5;i++) { l=1; for(j=0;j<16;j++) { if((zhuan[i]&l)==0) { Draw((int)((jx+tx)*((16*i+j)%8)+pianx+jx),(int)((jy+ty)*((int)((16*i+j)/8))+piany+jy),(int)tx,(int)ty); sum+=1; } l=l*2; } } gotoxy(5,4); printf("Press any key to start game...Q key to quit..."); ch=getch(); if(ch=='q'||ch=='Q') quitgame(); else { gotoxy(5,4); printf(" "); } for(;;) { setfillstyle(1, 0); bar(mx-bx/2,my,mx+bx/2,my+5); Msread(&mx, &my, &mb); Draw(mx-bx/2,my,bx,5); setcolor(0); mycircle(qx,qy,r,0); /*判断求是否反弹*/ if(qx-r<=pianx+1 || qx+r>=(tx+jx)*8+pianx-1) { flag=-flag; k=-k; } if(qy-r<=piany+1) k=-k; for(gi=0;gi<5;gi++) { l=1; for(gj=0;gj<16;gj++) { if((zhuan[gi]&l)==0) { j=(16*gi+gj)/8; i=(16*gi+gj)%8; x=(jx+tx)*i+jx+tx/2+pianx; y=(jy+ty)*j+jy+ty/2+piany; /*边判断1*/ if(qy>=y-ty/2 && qy<=y+ty/2 &&(pow(qx+r-x+tx/2,2)<1 || pow(qx-r-x-tx/2,2)<1)) { flag=-flag; k=-k; zhuan[gi]=zhuan[gi]|l; sum-=1; if(sum==0) wingame(); setfillstyle(1, 0); bar((jx+tx)*i+pianx+jx,(jy+ty)*j+piany+jy,(jx+tx)*i+pianx+jx+tx,(jy+ty)*j+piany+jy+ty); } else /*边判断2*/ if(qx>=x-tx/2 && qx<=x+tx/2 &&(pow(qy+r-y+ty/2,2)<1 || pow(qy-r-y-ty/2,2)<1)) { k=-k; zhuan[gi]=zhuan[gi]|l; sum-=1; if(sum==0) wingame(); setfillstyle(1, 0); bar((jx+tx)*i+pianx+jx,(jy+ty)*j+piany+jy,(jx+tx)*i+pianx+jx+tx,(jy+ty)*j+piany+jy+ty); } else /*角判断*/ if(pow(qx-x+tx/2,2)+pow(qy-y+ty/2,2)<=r*r || pow(qx-x-tx/2,2)+pow(qy-y+ty/2,2)<=r*r || pow(qx-x+tx/2,2)+pow(qy-y-ty/2,2)<=r*r || pow(qx-x-tx/2,2)+pow(qy-y-ty/2,2)<=r*r) { flag=-flag; zhuan[gi]=zhuan[gi]|l; sum-=1; if(sum==0) wingame(); setfillstyle(1, 0); bar((jx+tx)*i+pianx+jx,(jy+ty)*j+piany+jy,(jx+tx)*i+pianx+jx+tx,(jy+ty)*j+piany+jy+ty); } } l=l*2; } } /*棍棒的反弹*/ if(qx<=mx+bx/2 && qx>=mx-bx/2 && pow(qy+r-my,2)<1) { k=-(k/pow(k*k,0.5))*(0.3*bx/(pow(pow(qx-mx,2),0.5)+0.000001)); } if((int)(qy+r)>my+0.5) { gotoxy(5,5); printf("You have lost the game!Press any key to restart..."); getch(); goto star; } b=qy-qx*k; if(flag==1) qx=qx+speech/pow(1.0+k*k,0.5); if(flag==-1) qx=qx-speech/pow(1.0+k*k,0.5); qy=qx*k+b;/*计算球心坐标*/ setcolor(14); mycircle((int)qx,(int)qy,r,14); delay(1); if(mb==1) { gotoxy(5,5); printf("You have lost the game!Press any key to restart..."); getch(); goto star; } } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值