hdu5115 Dire Wolf【区间dp】
转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4361169.html ---by 墨染之樱花
【题目链接】http://acm.hdu.edu.cn/showproblem.php?pid=5115
【题目描述】有个冒险家要消灭一群狼,这些狼站成一排,每个狼都有一个基础攻击力,除此之外,每个狼还会对两边的狼有附加攻击力。不过当一个狼被消灭时,其对两边狼的附加攻击力就会消失,但是两边的狼就会变邻近,它们的附加攻击力就会相互作用。问消灭这一排狼所需要消耗的最小生命值(消灭一个狼所消耗的生命值为这匹狼的基础攻击力加两边狼的附加攻击力的总和)
【思路】简单的区间dp,dp[i][j]为消灭区间[i,j]的狼的最小消耗。思考将这个区间划分成两段[i,k]和[k+1,j]。先消灭[i,k]的狼的话k+1位置的狼的攻击力就会发生变化,即减去原本k位置提供的再加上新的i-1位置提供的。若先消灭[k+1,j]的话也一样修改。只需枚举[i,j]区间再枚举分割点k即可,复杂度O(n^3)。此外为了避免讨论端点,在0和n+1位置各加一个基础攻击力和附加攻击力均为0的狼。
/* *********************************************** Author :Kirisame_Marisa blog :http://www.cnblogs.com/KirisameMarisa/ Created Time :2015年03月23日 星期一 21时29分52秒 File Name :a.cpp ************************************************ */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=210; #define eps 1e-10 #define zero(x) (fabs(x)<eps) #define REP(X,N) for(int X=0;X<N;X++) #define REP2(X,L,R) for(int X=L;X<=R;X++) #define CLR(A,X) memset(A,X,sizeof(A)) #define PB(X) push_back(X) #define MP(X,Y) make_pair(X,Y) #define IT iterator #define test puts("OK") typedef long long ll; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<PII> VII; int n; int a[MAXN],b[MAXN]; int dp[MAXN][MAXN]; int main() { //freopen("in","r",stdin); //freopen("out","w",stdout); int T; scanf("%d",&T); REP(p,T) { scanf("%d",&n); REP2(i,1,n) scanf("%d",&a[i]); REP2(i,1,n) scanf("%d",&b[i]); a[0]=a[n+1]=b[0]=b[n+1]=0; REP2(i,1,n) dp[i][i]=a[i]+b[i-1]+b[i+1]; REP2(len,2,n) { REP2(i,1,n-len+1) { int s=i,t=i+len-1; dp[s][t]=INF; REP2(j,s,t-1) { int temp=min(-b[j]+b[s-1],-b[j+1]+b[t+1]); if(temp+dp[s][j]+dp[j+1][t]<dp[s][t]) dp[s][t]=temp+dp[s][j]+dp[j+1][t]; } } } printf("Case #%d: %d\n",p+1,dp[1][n]); } return 0; }