9018P1938恐狼后卫

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 }
View Code

 

posted @ 2017-10-30 15:29  lazytear  阅读(246)  评论(0编辑  收藏