1. 程式人生 > >[區間dp] Dire Wolf HDU

[區間dp] Dire Wolf HDU

區間DP 算是裸板吧 這次求的是最小值

題目大意:總共有N只狼排成一排,每隻狼都有一個基礎攻擊力ai,以及被擊殺後可給別的狼提供的攻擊力bi(一隻狼被攻擊的話,它相鄰的狼會為它提供額外的攻擊力bi),你擊殺一隻狼都會減少與這隻狼攻擊力加上相鄰的狼提供的額外的攻擊力的和的生命值,問如果要將全部狼都擊殺,你最少需要減少多少生命值。

列舉區間長度與起點,求出終點,然後列舉起點與終點之間的點。dp[i][j]為殺死i到j的狼所受到的傷害,然後列舉k作為最後一隻被殺死的狼,此時受到的傷害為attack[k]+extra[i-1]+extra[j+1],得到狀態轉移方程為: dp[i][j] = min(dp[i][j] , dp[i][k - 1] + dp[k + 1][j] + base[k] + extra[i - 1] + extra[j + 1]); 以K為分割點。。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;

const int maxn = 205;
const int mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double PI=acos(-1);

int n,m,t;
int dp[maxn][maxn];
int
attack[maxn]; int extra[maxn]; int main() { scanf("%d",&t); int cas=1; while(t--){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&attack[i]); for(int i=1;i<=n;i++) scanf("%d",&extra[i]); attack[0]=attack[n+1]=extra[0]=extra[n+1]=0; for
(int i=1;i<=n;i++){ for(int j=i;j<=n;j++){ dp[i][j]=INF; }// i從1到n-len 這樣每次用k分割更新左到右 區間最小值 }// for(int len=0;len<=n;len++){ for(int i=1;i<=n-len;i++){ int j=i+len; for(int k=i;k<=j;k++){ dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+attack[k]+extra[i-1]+extra[j+1]); } } } printf("Case #%d: %d\n",cas++,dp[1][n]); } return 0; }