2012-A3-0020

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

题意:甲依次经过N个部分,每个部分或者积累0(满5个不可再增加),或者可以和一个??对打,对打是回合制,

每回合,甲先发动攻击,然后??还击,每回合甲有一次机会喝药恢复P个hp(hp有上限),blablabla

求甲最多可打坏多少个??,以及此情况下的最少喝药次数..


此题极不厚道的一点是,甲的攻击输出,最大HP,和恢复的P在一组case的最后,这样需要开一个数组存下之前的输入,不能在输入时完成运算,增加了额外的空间复杂度。

然后以f[i:0..5],表示分别积累了i个0后,可以打掉的??以及此状况下最少喝药次数

计算时,假设甲可以打掉??,这样可以算出要扛??回击伤害的次数。

然后计算需要的最少喝药次数,分P比一次伤害小或者不小讨论出贪心模拟出结果即可。
{{{
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef pair<int,int> xx;
#define hp first
#define us second
#define inf -(1<<27)
int h[51200],d[51200],x[51200],H,D,P;
xx f[6];
void cmx(xx&a,xx b){if(a<b)a=b;}
const xx operator+(const xx& a,const xx& b){return xx(a.hp+b.hp,a.us+b.us);}
xx battle(int k,int d){
    if(H>k*d)return xx(1,0);
    if(d>=H)return xx(inf,0);
    for(int i=1,r=H,a=0;i<=k&&r>0;++i){
        if(r<=d)++a,r=min(H,r+P);
        r-=d;
        if(a<i&&P<d){r+=P;++a;}
        if(r>d*(k-i))return xx(1,-a);
    }
    return xx(inf,0);
}
int main(){
    for(int m,n;~scanf("%d ",&n);memset(x,0,m+1<<2)){
        for(m=0;n--;getchar()=='0'?++x[m],getchar():(scanf("%d%d ",h+m,d+m),m++));
        scanf("%d%d%d",&H,&D,&P);P=min(H-1,P);
        f[0]=xx(0,0);f[1]=f[2]=f[3]=f[4]=f[5]=xx(inf,0);
        for(int i=0;i<m;++i){
            for(int j=min(5,x[i]);j--;)
                for(int k=5;k--;)cmx(f[k+1],f[k]);
            cmx(f[0],f[5]+battle((h[i]-1)/D,d[i]));
        }
        printf("%d %d\n",f[0].hp,-f[0].us);
    }
}
}}}

题意:甲依次经过N个部分,每个部分或者积累0(满5个不可再增加),或者可以和一个??对打,对打是回合制,

每回合,甲先发动攻击,然后??还击,每回合甲有一次机会喝药恢复P个hp(hp有上限),blablabla

求甲最多可打坏多少个??,以及此情况下的最少喝药次数..

此题极不厚道的一点是,甲的攻击输出,最大HP,和恢复的P在一组case的最后,这样需要开一个数组存下之前的输入,不能在输入时完成运算,增加了额外的空间复杂度。

然后以f[i:0..5],表示分别积累了i个0后,可以打掉的??以及此状况下最少喝药次数

计算时,假设甲可以打掉??,这样可以算出要扛??回击伤害的次数。

然后计算需要的最少喝药次数,分P比一次伤害小或者不小讨论出贪心模拟出结果即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef pair<int,int> xx;
#define hp first
#define us second
#define inf -(1<<27)
int h[51200],d[51200],x[51200],H,D,P;
xx f[6];
void cmx(xx&a,xx b){if(a<b)a=b;}
const xx operator+(const xx& a,const xx& b){return xx(a.hp+b.hp,a.us+b.us);}
xx battle(int k,int d){
    if(H>k*d)return xx(1,0);
    if(d>=H)return xx(inf,0);
    for(int i=1,r=H,a=0;i<=k&&r>0;++i){
        if(r<=d)++a,r=min(H,r+P);
        r-=d;
        if(a<i&&P<d){r+=P;++a;}
        if(r>d*(k-i))return xx(1,-a);
    }
    return xx(inf,0);
}
int main(){
    for(int m,n;~scanf("%d ",&n);memset(x,0,m+1<<2)){
        for(m=0;n--;getchar()=='0'?++x[m],getchar():(scanf("%d%d ",h+m,d+m),m++));
        scanf("%d%d%d",&H,&D,&P);P=min(H-1,P);
        f[0]=xx(0,0);f[1]=f[2]=f[3]=f[4]=f[5]=xx(inf,0);
        for(int i=0;i<m;++i){
            for(int j=min(5,x[i]);j--;)
                for(int k=5;k--;)cmx(f[k+1],f[k]);
            cmx(f[0],f[5]+battle((h[i]-1)/D,d[i]));
        }
        printf("%d %d\n",f[0].hp,-f[0].us);
    }
}