2017.01.20省冬的题……
题目描述
著名卡牌游戏《石炉传说》中有一张随从牌:恐狼后卫。恐狼后卫的能力是使得相邻随从的攻击力提高。
现在有n张恐狼后卫顺序排成一排,第i只恐狼后卫的攻击力为a[i],血量为h[i],提升相邻随从的攻击力值为b[i]。
你的攻击力为atk,每次攻击你可以选择一只存活的恐狼后卫,减少其血量值atk。若其血量小于等于0,则该恐狼后卫死亡。当某只恐狼后卫死亡时,其左右两侧(若存在)的恐狼后卫会靠拢并成为相邻关系。
在攻击第i只恐狼后卫时,除了要承受这只恐狼后卫自身的攻击力a[i]之外,还要承受与其相邻的2张恐狼后卫的提高攻击力值b[i-1]和b[i+1](若存在)。
输入
第一行一个正整数n,表示恐狼后卫的数量。
第二行一个正整数atk,表示你的攻击力。
以下n行,每行3个值:a[i]、b[i]、h[i],分别表示第i只恐狼后卫自身的攻击力值、提升相邻随从的攻击力值、血量值。
输出
一个整数,表示杀死所有恐狼后卫需要承受的最少伤害值。
样例输入
3
1
8 1 6
3 5 7
4 9 2
样例输出
94
提示
对于30%的数据,n <= 10
对于另外30%的数据,n <= 100, h[i] = 1
对于100%的数据,n <= 400,atk、a[i]、b[i]、h[i] <= 1000
solution:
这题明显是一道区间dp吧……
我们定义f[i][j]为消灭第i号狼到第j号狼的最小代价
然后显然可以从上一步转移过来,也就是i到j号狼中只剩下第k号狼还活着的状态。
因此我们写出方程:f[i][j]=min(f[i][j],f[i][k-1]+f[k][j+1]+(a[k]+b[i-1]+b[i+1])*(h[k]-1/atk+1))
只需要注意处理状态的顺序即可……
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #define inf 0x7fffffff 8 using namespace std; 9 int n,atk; 10 int a[510],b[510],h[510]; 11 int dp[510][510]; 12 int min(int a,int b){ 13 return a<b?a:b; 14 } 15 int chu(int a,int b){ 16 return (a-1)/b+1; 17 } 18 int main(){ 19 int i,j,k; 20 scanf("%d%d",&n,&atk); 21 for(i=1;i<=n;++i){ 22 scanf("%d%d%d",&a[i],&b[i],&h[i]); 23 } 24 for(i=1;i<=n;++i){ 25 dp[i][i]=(a[i]+b[i-1]+b[i+1])*chu(h[i],atk); 26 } 27 for(i=1;i<n;++i){ 28 for(j=1;j+i<=n;++j){ 29 dp[j][j+i]=inf; 30 for(k=j;k<=j+i;++k){ 31 dp[j][j+i]=min(dp[j][j+i],dp[j][k-1]+dp[k+1][j+i]+(a[k]+b[j-1]+b[j+i+1])*chu(h[k],atk)); 32 } 33 } 34 } 35 printf("%d\n",dp[1][n]); 36 return 0; 37 }