题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5115
题意:
有n只狼,每只狼有两种属性,一种攻击力一种附加值,我们没杀一只狼,那么我们受到的伤害值为
这只狼的攻击值与它旁边的两只狼的附加值的和,求把所有狼都杀光受到的最小的伤害值。
分析:
赤裸裸的区间DP
dp[i][j]表示把区间i,j内的所有狼杀光所受到的最小的伤害。
状态转移方程为
dp[i][j]=min{dp[i][k]+dp[k+1][j]-b[k]+b[i+1],dp[i][k]+dp[k+1][j]-b[k+1]+b[j+1]}(i<=k<j)这里讨论了先杀左边的还是先杀右边的
处理的时候要注意a[0],b[0],a[n+1],b[n+1]的初值都是0.
代码如下:
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 210; int dp[maxn][maxn]; int a[maxn],b[maxn]; int main() { int n,t,cas=1; scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&b[i]); a[0]=a[n+1]=0; b[0]=b[n+1]=0; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) dp[i][i]=a[i]+b[i-1]+b[i+1]; for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) dp[i][j]=999999999; for(int len = 2;len<=n;len++){ for(int i=1;i+len-1<=n;i++){ int j=i+len-1; for(int k=i;k<j;k++){ dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+b[i-1]-b[k]); dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+b[j+1]-b[k+1]); } } } printf("Case #%d: %d\n",cas++,dp[1][n]); } return 0; }