题意:Matt面前有n匹狼排成一排,他要将这些狼全部杀死才能活下来,第i匹狼有两个数据ai,bi,分别表示它的基础攻击力和它能为相邻的狼带来的附加攻击力。其中一匹狼被杀死后,它左右的狼视为相邻,Matt将受到它的基础攻击力与它左右的狼带来的附加攻击力之和的伤害,求要活下来受到到最小伤害。(n<=200)
无论是怎样的转移,都无疑是由小区间推得大区间,现在dp[L][R]表示杀死区间[L,R]内的狼受到的最小伤害,为了转移状态需要分割区间。我们设区间[L,R]中最后一个杀死的是k号狼,那么杀死k号狼受到的伤害即为b[L-1]+b[R+1]+a[k],转移方程为dp[L][R]=min{dp[L][k-1]+dp[k+1][R]+a[k]+b[L-1]+b[R+1]}
#include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define FOR(i,x,y) for(int i=(x);i<=(y);i++) #define DOR(i,x,y) for(int i=(x);i>=(y);i--) #define memclear(a) memset(a,0,sizeof(a)) #define N 200 using namespace std; int a[N+3],b[N+3]; int dp[N+3][N+3]; int main() { int T; scanf("%d",&T); FOR(Ti,1,T) { memclear(a);memclear(b);memclear(dp); int n; scanf("%d",&n); FOR(i,1,n)scanf("%d",&a[i]); FOR(i,1,n)scanf("%d",&b[i]); FOR(l,1,n) //枚举区间长度 FOR(L,1,n-l+1) //枚举左端点 { int R=L+l-1; dp[L][R]=1e9; FOR(k,L,R) //k为区间[L,R]中最后杀死的狼 dp[L][R]=min(dp[L][R],dp[L][k-1]+dp[k+1][R]+a[k]+b[L-1]+b[R+1]); } printf("Case #%d: %d\n",Ti,dp[1][n]); } return 0; }