 /**//*
題意:N只鳥要攻擊K個怪物,每只鳥有相應(yīng)的power值n,每個怪物也有相應(yīng)的生命值m
一只鳥剛放出時為young(n可以為0),攻擊了怪物后變?yōu)閛ld 當(dāng)它的power變?yōu)?時就死掉了
規(guī)則為:
1) n>m 怪物死掉,下一個怪物出現(xiàn)
2) n=m 鳥,怪物同時死掉
3) n<m 鳥為young時,能讓怪物損失n old時,不會損失
同時,可以使用M個魔法,每個魔法只能對一只鳥使用,可以使得它的power加倍
dp[i][j]表示前j只鳥使用了i個魔法最大殺死的怪物
這里用個pair來存
<first,second> 表示第first怪物還剩second的血,取-1表示已經(jīng)死掉了(也即等價于first+1,saber[first+1])
由于power,生命值可以為0,比較繁瑣,大致算法為:
對于新放出來的鳥j 設(shè)其power為 now
if(now <= blood )
blood -= now
blood 為0時標(biāo)記-1死掉
else
殺死當(dāng)前怪物,num++
while(now >0 && 能繼續(xù)殺 ) //這里now不能為0,因為已經(jīng)是old的了
now -= saber[num++]

*/
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;


pair<int,int> dp[105][10005];
int bird[10005],saber[100005];
int N,M,K;


inline pair<int,int> pmax( pair<int,int> &A , pair<int,int> &B)
  {
if(A.first > B.first )return A;
if(A.first == B.first && A.second < B.second)return A;
return B;
}

int DP()
  {
//-1 died
dp[0][0] = make_pair(0,-1);
for(int i=0;i<=M;i++)
for(int j=i?i:1;j<=N;j++)
 {
dp[i][j] = make_pair(0,-1);
//[i-1,j-1]
if(i)
 {
int now = bird[j]*2;
int num = dp[i-1][j-1].first;
int blood = dp[i-1][j-1].second;
//change
if(blood == -1)blood = saber[++num];
if(num>K)return K;
if(now <= blood)
 {
blood -= now;
if(blood == 0) blood = -1;
dp[i][j] = pmax(dp[i][j],make_pair(num,blood));
}
else
 {
now -= blood;
num++;
while(now && num<=K && now >= saber[num] )//now can't be 0 it's old
now -= saber[num++];
if(num>K)return K;
blood = saber[num];
dp[i][j] = pmax(dp[i][j],make_pair(num,blood));
}
}
//[i,j-1]
 {
int now = bird[j];
int num = dp[i][j-1].first;
int blood = dp[i][j-1].second;
//change
if(blood == -1)blood = saber[++num];
if(num>K)return K;
if(now <= blood)
 {
blood -= now;
if(blood == 0) blood = -1;
dp[i][j] = pmax(dp[i][j],make_pair(num,blood));
}
else
 {
now -= blood;
num++;
while(now && num<=K && now >= saber[num] )//now can't be 0 it's old
now -= saber[num++];
if(num>K)return K;
blood = saber[num];
dp[i][j] = pmax(dp[i][j],make_pair(num,blood));
}
}
}
if(dp[M][N].second!=-1)dp[M][N].first--;
return dp[M][N].first;
}

int main()
  {
//freopen("in","r",stdin);
while(scanf("%d%d%d",&N,&M,&K),N||M||K)
 {
M = min(N,M);//一定要加 上面的判斷條件 j=i?i:1
for(int i=1;i<=N;i++)
scanf("%d",&bird[i]);
for(int i=1;i<=K;i++)
scanf("%d",&saber[i]);
printf("%d\n",DP());
}
return 0;
}
|
|
常用鏈接
隨筆分類
Links
搜索
最新評論

|
|