HDU-5115Dire Wolf(区间DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5115
题目大意:有T组数据,每组数据有n只野狼,接下来一行有n个数据,代表杀掉这只狼要承受的伤害,接下来一行n数据,与上一行相对应,代表杀掉第i只狼后,会受到这只狼左边和右边的附加伤害,问杀掉所有狼的最小伤害是多少?
Sample Input
2 3 3 5 7 8 2 0 10 1 3 5 7 9 2 4 6 8 10 9 4 1 2 1 2 1 4 5 1
Sample Output
Case #1: 17 Case #2: 74
emmmm,区间DP,状态$dp[i][j]$表示的是杀死区间$[i,j]$所耗费的最小代价,那么跟合并石子的有些类似,我们枚举区间长度,枚举起点,得到终点,再枚举分割点,只不过有一点点不太一样。它的状态转移方程是这样的:$dp[l][r]=min(dp[l][r],dp[l][mid-1]+a[mid]+dp[mid+1][r]+b[l-1]+b[r+1])$。emmm,感觉可以望文生义了。。。。
以下是AC代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int mac=250; const int inf=1e8+10; int a[mac],b[mac]; int dp[mac][mac]; int main() { int t,n,Case=0; scanf ("%d",&t); while (t--){ scanf ("%d",&n); memset(b,0,sizeof b); for (int i=1; i<=n; i++) for (int j=i; j<=n; j++) dp[i][j]=inf; for (int i=1; i<=n; i++) scanf ("%d",&a[i]); for (int i=1; i<=n; i++) scanf ("%d",&b[i]); for (int i=1; i<=n; i++) dp[i][i]=a[i]+b[i-1]+b[i+1]; for (int len=2; len<=n; len++){ for (int l=1; l+len-1<=n; l++){ int r=l+len-1; for (int mid=l; mid<=r; mid++) dp[l][r]=min(dp[l][r],dp[l][mid-1]+a[mid]+dp[mid+1][r]+b[l-1]+b[r+1]); } } printf ("Case #%d: %d\n",++Case,dp[1][n]); } return 0; }
路漫漫兮