hdu5115 Dire Wolf(区间dp)

题意:

有n头狼排成一排,每只狼两个属性,攻击力a(i)和加成值b(i)。
狼的实际攻击力等于自身攻击力加相邻狼的加成值。
被杀死之后的狼对相邻的狼的攻击力的加成会被取消,
同时,原先与 被杀死的狼相邻的两头狼会变成相邻的狼。
问杀死所有狼受到的伤害值最小是多少

数据范围:n<=200

解法:

区间dp,
令d[i][j]表示击杀[i,j]的所有狼所需要的最小代价,
转移方程:
枚举最后一只杀的狼k,d[i][j]=d[i][k-1]+d[k+1][j]+(a[k]+b[i-1]+b[j+1]).

解释一下转移方程:
先杀d[i][k-1]和d[k+1][j],
那么最后i-1,k,j+1相邻,杀k的代价为(a[k]+b[i-1]+b[j+1]).

code:

#include 
#define int long long
using namespace std;
const int maxm=205;
int d[maxm][maxm];
int a[maxm];
int b[maxm];
int n;
signed main(){
     
    ios::sync_with_stdio(0);
    int T;cin>>T;
    int cas=1;
    while(T--){
     
        //input
        cin>>n;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n;i++)cin>>b[i];
        b[n+1]=0;
        //init
        for(int i=1;i<=n;i++){
     
            for(int j=i;j<=n;j++){
     
                d[i][j]=1e18;
            }
        }
        //dp
        for(int i=1;i<=n;i++){
     
            d[i][i]=a[i]+b[i-1]+b[i+1];
        }
        for(int len=2;len<=n;len++){
     
            for(int i=1;i<=n;i++){
     
                int j=i+len-1;
                if(j>n)break;
                for(int k=i;k<=j;k++){
     
                    d[i][j]=min(d[i][j],d[i][k-1]+d[k+1][j]+a[k]+b[i-1]+b[j+1]);
                }
            }
        }
        //output
        cout<<"Case #"<<cas++<<": "<<d[1][n]<<endl;
    }
	return 0;
}

你可能感兴趣的:(hdu5115 Dire Wolf(区间dp))