hdu 4283 You Are the One 区间dp
参考了别人的思路
dp[i][j]表示从第i个人到第j个人这段区间的最小花费是只考虑这j-i+1个人,不需要考虑前面有多少人)那么对于dp[i][j]的第i个人,、就有可能第1个上场,也可以第j-i+1个上场。考虑第K个上场即在i+1之后的K-1个人是率先上场的,那么就出现了一个子问题 dp[i+1][i+1+k-1-1]表示在第i个人之前上场的对于第i个人,由于是第k个上场的,那么愤怒值便是val[i]*(k-1)其余的人是排在第k+1个之后出场的,也就是一个子问题dp[i+k][j],对于这个区间的人,由于排在第k+1个之后,所以整体愤怒值要加上k(sigma(i+k--j))
为什么若 i是第K个上场就是 i+1之后的K-1个人是率先上场的 因为i是第一个入栈的 到i出栈的时候i也会是栈里的最后一个 此时他是第k个出栈的那肯定就是他后面的K-1个人是率先出栈的咯
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #define maxx 10000002 5 using namespace std; 6 7 int dp[102][102],a[102],sum[102]; 8 9 int solve(int n) 10 { 11 memset(dp,0,sizeof(dp)); 12 for(int i=0;i<=n;i++) 13 for(int j=i+1;j<=n;j++) 14 dp[i][j]=maxx; 15 16 for(int l=2;l<=n;l++) 17 { 18 for(int i=1;i+l-1<=n;i++) 19 { 20 int j=i+l-1; 21 for(int k=1;k<=l;k++) 22 dp[i][j]=min(dp[i][j],a[i]*(k-1)+dp[i+1][i+k-1]+dp[i+k][j]+k*(sum[j]-sum[i+k-1])); 23 } 24 } 25 return dp[1][n]; 26 } 27 28 int main() 29 { 30 int t,n,m,i,j,p=1; 31 scanf("%d",&t); 32 while(t--) 33 { 34 scanf("%d",&n); 35 memset(sum,0,sizeof(sum)); 36 for(i=1;i<=n;i++) 37 { 38 scanf("%d",&a[i]); 39 sum[i]=sum[i-1]+a[i]; 40 } 41 printf("Case #%d: %d\n",p++,solve(n)); 42 } 43 return 0; 44 }