湘潭oj_1246 Heartst

有些许想法..尝试:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int L=1000000007;
int b[3];//b[1],b[2]分别记录怪物 hp%3后 余1和余2的个数
int main(){
     int i,n,m,x;
    while(scanf("%d%d",&n,&m)!=EOF){
       memset(b,0,sizeof(b));
          int s=0; 
        //s:记录怪物只用减3技能打需要的次数。
        for(i=1;i<=n;i++)
         {
          scanf("%d",&x);
          s+=x/3;
          int y=x%3;
          if(y)
            {
                s+=1;
               b[y]++;
            }
         }
        int num=b[1]+b[2],sum=0,temp;
        for(i=0;i<=m;i++)
        {
            temp=s;  
            if(num>=i) {  //所给减2技能比较少的情况。
                temp-=i;
            }
            else{        //所给减2技能比较多的情况。
                temp-=num;
                temp-=i*2/3;//bug
                //用多余的减2技能代替减3技能打的那部分血量-bug
                //hp=6时3-2(三个减2技能相当二个减2技能)hp=3时却是2-1
            }
            //printf("temp=%d\n",temp);//temp代表f(i)
            sum+=temp; //
            if(sum>=L) sum%=L;
        }
     printf("%d\n",sum);
    }
return 0;
}
消除bug  考虑采用能想到的最优打怪思想更有保障

ac后的总结:打怪的贪心问题,打怪时的最优解是: 怪hp%3 , 余2时使用一次减2点技能再使用减3技能,这样的攻击最有效;余1时使用二次减2点的技能,使剩下的血量为3的倍数再使用减3技能,这样的攻击最有效(hp==1时要特殊处理);知道了最优的解决方案,接下来就是对多给的一定量的2技能的使用了。
ps:需明白最优解时如果不用减2技能那就要用相等数目的减3技能来代替

#include<cstdio>
#include<iostream>
using namespace std;
const int L=1000000007;
int main(){
    int i,x,n,m;
    while(~scanf("%d%d",&n,&m))
    {
   //s是最佳打怪方案时需要的减2技能数
   //sum是最佳打怪方案时需要的减3技能数,
   //hp被减2技能打后含奇数个3时就少使用一次减3技能用p++记录上,
   //能用来消上一个代码出现的bug。
   // 这样最佳情况下打怪需s+sum+p次
        int s=0,p=0,sum=0;
       for(i=1;i<=n;i++)
       {
           scanf("%d",&x);
           if(x==1)
           {
               s+=1;
           }
           else if(x%3==1)
           {
               s+=2;
               if((x-4)/3%2==1) {p++;sum+=(x-7)/3;}
               else sum+=(x-4)/3;
           }
           else if(x%3==2)
           {
               s+=1;
               if((x-2)/3%2==1) {p++;sum+=(x-5)/3;}
               else sum+=(x-2)/3;
           }
           else if(x%3==0)
           {
               if((x/3)%2==1) {p++;sum+=(x-3)/3;}
               else {sum+=x/3;}
           }
       }
       int l=0;   
       for(i=0;i<=m;i++)
       {
           if(i<=s)
           {
               l+=(s-i+sum+p);
           }
           else if(i>s)
           {
              if((i-s)<=(sum*3/2))
              {
                  l+=(sum-(i-s)*2/3+p);
              }
              else
              {
                 l+=(p-(i-s-sum*3/2)/2);
              }
           }
           if(l<=0) {l=0;break;}
           if(l>=L) l%=L;
       }
       printf("%d\n",l);
    }
return 0;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值