明天还要期末考试今天还在浪。。。
题目链接:bzoj 2964
说来惭愧这题的思路是从网上找的题解看的,本来觉着很好写,真正写起来才发现有不少需要注意的地方;
主体思路是将法攻和怒功分开dp,本来以为关于恢复生命的技能的使用次数做个加减法就好了,事实上并没有这么简单,只好再进行一次dp;
由于本人太弱,实在想不起如何从i-1向i转移,只能从i向i+1进行向后转移,好像这样也易于理解?
其中一定要牢记技能攻击的顺序,是先加血再受伤!!!
代码:
#include<cstdio>
#include<algorithm>
const int maxn=1005;
using std::max;
using std::min;
int t,n,m,hp,mp,sp,dhp,dmp,dsp,x;
int DP[maxn][maxn];
struct asd
{
int xh,ct;
};
asd b[11];
asd c[11];
void dtgh(int N,int sh,int hf,int maxp,asd *a,int num,int *ans)
{
for(int i=0;i<=N;i++)
{
ans[i]=0;
for(int j=0;j<=maxp;j++)
DP[i][j]=0;
}
for(int i=0;i<N;i++)
{
for(int j=0;j<=maxp;j++)
{
for(int k=0;k<=num;k++)
if(k==0)
{
int tmp=j+hf;
if(tmp>maxp)tmp=maxp;
DP[i+1][tmp]=max(DP[i][j]+sh,DP[i+1][tmp]);
}
else if(j>=a[k].xh)
DP[i+1][j-a[k].xh]=max(DP[i+1][j-a[k].xh],DP[i][j]+a[k].ct);
ans[i]=max(ans[i],DP[i][j]);
}
}
for(int i=0;i<=maxp;i++)ans[N]=max(ans[N],DP[N][i]);
}
int ai[maxn];
int ans1[maxn],ans2[maxn];
int bld[maxn][maxn];
int tim[maxn];
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d%d%d%d%d%d%d",&n,&m,&hp,&mp,&sp,&dhp,&dmp,&dsp,&x);
for(int i=1;i<=n;i++)scanf("%d",&ai[i]);
int tmp;
scanf("%d",&tmp);
for(int i=1;i<=tmp;i++)scanf("%d%d",&b[i].xh,&b[i].ct);
dtgh(n,0,dmp,mp,b,tmp,ans1);
scanf("%d",&tmp);
for(int i=1;i<=tmp;i++)scanf("%d%d",&c[i].xh,&c[i].ct);
dtgh(n,x,dsp,sp,c,tmp,ans2);
int flag=0;
int rhp=hp;
tim[0]=0;
for(int i=0;i<=n;i++)tim[i]=n+1;
for(int i=0;i<=n;i++)
for(int j=0;j<=hp;j++)bld[i][j]=n+1;
bld[0][hp]=0;
for(int i=0;i<n;i++)
{
for(int j=1;j<=hp;j++)
{
int tmp=j-ai[i+1];
if(tmp>0)
bld[i+1][tmp]=min(bld[i+1][tmp],bld[i][j]);
if(j!=hp)
{
tmp=j+dhp;
if(tmp>hp)tmp=hp;
tmp-=ai[i+1];//注意如果生命值满了需要先加生命再受伤,这地方坑了我好久;
if(tmp>0)
bld[i+1][tmp]=min(bld[i+1][tmp],bld[i][j]+1);
}
tim[i]=min(tim[i],bld[i][j]);
}
}
for(int i=1;i<=hp;i++)tim[n]=min(tim[n],bld[n][i]);
for(int i=1;i<=n;i++)
{
int tmpsh=0;
for(int k=0;k<=i-tim[i-1];k++)
tmpsh=max(ans1[k]+ans2[i-tim[i-1]-k],tmpsh);
if(m<=tmpsh)
{
printf("Yes %d\n",i);
flag=1;
break;
}
if(tim[i]>i)
{
printf("No\n");
flag=1;
break;
}
}
if(!flag)printf("Tie\n");
}
return 0;
}