1. 程式人生 > >Dire Wolf【區間DP】【完整解題報告記錄推導過程】

Dire Wolf【區間DP】【完整解題報告記錄推導過程】

  思路

  這個是一個DP的題目,原因是前一刻的狀態會影響到後一刻的狀態,所以我從DP的角度來思考這道題的解法,我想的是假如【i,j】的狼已經被吃完了,那麼接下來【i-1,j+1】的狼就會受到【i,j】的影響,只要判斷【i,j+1】和【i-1,j】哪個區間段再加上對應加上的狼的BUFF需求即可,但這還不夠(會WA的嘛,肯定還有BUG),那麼BUG在哪呢?我們目前確定的是從中心區域直接向外拓展時候的狀況,但是,假如子區間內有更優解,我們卻丟失了它怎麼辦,所以,我們需要完善。

  優化:對於【i,j】這個區間,我們還得更新其子區間,我們設一個k從【i, j-1】這個區間段一一遍歷,那麼我們殺狼【i,j】可以看作殺狼【i,k】+【k+1,j】
,但是作為dp,我們在改變其狀態不能忘記先決條件也已經改變了,我們先殺了【i,k】的狼,那麼殺【k+1,j】的狼,它的BUFF就變了,殺第k+1個狼的時候,它的左BUFF就不是k了,而是變成了i-1,因為【i,k】狼已死。

DP狀態轉移方程

最先的時候先是:dp[i][j]=min(dp[i+1][j] + a[i-1] + a[j+1], dp[i][j-1] + a[i-1] + a[j+1]);

dp[i][j]=min(dp[i][j], dp[i][k] + dp[k+1][j] - a[k] + a[i-1])。

完整程式碼

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef long long ll;
const int maxN=205;
int N, sum;
int dp[maxN][maxN], a[maxN];
int main()
{
    int T;
    scanf("%d", &T);
    for(int Cas=1; Cas<=T; Cas++)
    {
        scanf("%d", &N);    sum=0;  memset(dp, 0, sizeof(dp));  memset(a, 0, sizeof(a));
        for(int i=1; i<=N; i++)
        {
            int e1; scanf("%d", &e1);
            sum+=e1;
        }
        for(int i=1; i<=N; i++) scanf("%d", &a[i]);
        for(int i=1; i<=N; i++)
        {
            for(int j=i; j>=1; j--)
            {
                dp[j][i]=min(dp[j+1][i] + a[j-1] + a[i+1], dp[j][i-1] + a[i+1] + a[j-1]);
                for(int k=j; k<=i-1; k++)
                {
                    dp[j][i]=min(dp[j][i], dp[j][k] - a[k] + a[j-1] + dp[k+1][i]);
                }
            }
        }
        sum+=dp[1][N];
        printf("Case #%d: %d\n", Cas, sum);
    }
    return 0;
}