标签:
这题是区间DP。
题目的意思是ai表示每头狼的本身具备的攻击力,bi表示能提供给相邻狼的攻击力,以什么样的顺序去杀狼可以使狼对人的攻击最少。
且如果狼被杀了,就不能为相邻的狼提供攻击力了。
动态转移方程为dp[i][j]=min(dp[i][k]+dp[k][j]+a[k]+a[i]+a[j],dp[i][j])(j<k<i);
i表示以第i头狼为右端点(还未斩杀),j表示以第j头狼为左端点(还未斩杀)。
dp[i][j]记录的为以i,j未选时,那个而i-j已选好的最小的攻击。
(这道题做的我。。。。花了差不多一天时间,中间想想发发呆,就这种状态。还是懒,,,,然而现在还没有想的太明白。。。。。。。。)。
首先a,b数组两端要多加一位,a[0]=0;b[0]=0;a[p+1]=0;b[p+1]=0;
因为要把所有的狼都杀完,因为每次都要有两端,所以要杀完就必须是0-p+1内的编号1到p的狼,1左,p右端必须要有个端点。最后答案就是dp[p+1][0];
先给代码上完课回来注释:
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<stdlib.h> 5 #include<string.h> 6 using namespace std; 7 long long N=1e16; 8 typedef long long ll; 9 int main(void) 10 { 11 int i,j,k,p,q; 12 ll dp[300][300]; 13 ll a[300]; 14 ll b[300]; 15 scanf("%d",&k); 16 for(i=1; i<=k; i++) 17 { 18 scanf("%d",&p); 19 memset(a,0,sizeof(a)); 20 memset(b,0,sizeof(b)); 21 for(j=1; j<=p; j++) 22 scanf("%lld",&a[j]); 23 for(j=1; j<=p; j++) 24 scanf("%lld",&b[j]); 25 int n,m,t; 26 memset(dp,0,sizeof(dp)); 27 for(n=2; n<=p+1; n++) 28 { 29 for(m=n-2; m>=0; m--) 30 { 31 dp[n][m]=dp[n][n-1]+dp[n-1][m]+a[n-1]+b[n]+b[m]; 32 for(t=n-1; t>m; t--) 33 { 34 35 dp[n][m]=min(dp[n][t]+dp[t][m]+b[n]+a[t]+b[m],dp[n][m]); 36 } 37 } 38 39 } 40 printf("Case #%d: %lld\n",i,dp[p+1][0]); 41 } 42 return 0; 43 44 }
标签:
原文地址:http://www.cnblogs.com/zzuli2sjy/p/4955774.html