题目大意
著名卡牌游戏《石炉传说》中有一张随从牌:恐狼后卫。恐狼后卫的能力是使得相邻随从的攻击力提高。
现在有n张恐狼后卫顺序排成一排,第i只恐狼后卫的攻击力为ai,血量为hi,提升相邻随从的攻击力值为bi。你的攻击力为atk,每次攻击你可以选择一只存活的恐狼后卫,减少其血量值atk。若其血量小于等于0,则该恐狼后卫死亡。当某只恐狼后卫死亡时,其左右两侧(若存在)的恐狼后卫会靠拢并成为相邻关系。在攻击第i只恐狼后卫时,除了要承受这只恐狼后卫自身的攻击力ai之外,还要承受与其相邻的2张恐狼后卫的提高攻击力值bi−1和bi+1(若存在)。
你的任务是承受最少的总伤害杀死所有恐狼后卫,输出需承受的伤害值。
输入格式
第一行一个正整数n,表示恐狼后卫的数量。
第二行一个正整数atk,表示你的攻击力。
以下n行,每行3个值:ai、bi、hi,分别表示第i只恐狼后卫自身的攻击力值、提升相邻随从的攻击力值、血量值。
输出格式
一个整数,表示杀死所有恐狼后卫需要承受的最少伤害值。
样例输入
3
1
8 1 6
3 5 7
4 9 2
样例输出
94
数据规模与约定
对于30%的数据,n≤10
对于另外30%的数据,n≤100,hi=1
对于100%的数据,n≤400,atk,ai,bi,hi≤1000
分析
首先吐槽下恐狼后卫好像是炉石传说中的,而不是石炉传说中的,233,然后看题,第一眼感觉不可做,不可做要做呀,分析后觉得这是道区间DP,设左端点为j,右端点为i+j,中间随意一点为k,代价设为al,可知al[i][j]={al[j][k-1]+al[k+1][j]+去除k的代价}min,所以用三层循环,分别为i,j,k(注意i在最外层),可列状态转移方程al[j][j+i]=min(al[j][j+i],al[j][k-1]+al[k+1][j+i]+ (a[k]+b[j-1]+b[j+i+1])*(h[k]/atk+1));
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int a[405],b[405],h[405],al[405][405],n,atk;
int main(){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(h,0,sizeof(h));
memset(al,0,sizeof(al));
scanf("%d%d",&n,&atk);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&a[i],&b[i],&h[i]);
for(int i=1;i<=n;i++)
h[i]--;
for(int i=1;i<=n;i++)
al[i][i]=(a[i]+b[i-1]+b[i+1])*(h[i]/atk+1);
for(int i=1;i<n;i++){
for(int j=1;j<=n-i;j++){
al[j][j+i]=(1<<30);
for(int k=j;k<=j+i;k++){
int l=al[j][k-1]+al[k+1][j+i];
int m=(a[k]+b[j-1]+b[j+i+1])*(h[k]/atk+1);
al[j][j+i]=min(al[j][j+i],l+m);
}
}
}
printf("%d\n",al[1][n]);
return 0;
}