题意:有一个队列,每个人有一个愤怒值a[i],如果他是第k个上场,不开心指数就为(k-1)*a[i]。但是边上有一个小黑屋(其实就是个堆栈),可以一定程度上调整上场程序
思路:枚举区间和每个人第几个上场
dp[i][j]:[i,j]的最小分数
假设区间[i,j],第i个人第k个出场(1<=k<=j-i+1),如果第i个人第k个出场,则他之前有k-1个人出场:dp[i+1][i+k-1](应为枚举第i个人,所以从i+1开始)
然后后面剩的人又是一个子区间:dp[k+i][j] 当然在这之前有k个人先出场所以还要加上(sum[j]-sum[i+k-1])*k的值;sum[i]表示i之前所有不开心值的和
最后加上第i个人出场前的不开心值a[i]*(k-1)
dp[i][j]=min(dp[i][j],dp[i+1][k+i-1]+dp[k+i][j]+a[i]*(k-1)+(sum[j]-sum[k+i-1])*k);
1 //#pragma comment(linker, "/STACK:167772160")//手动扩栈~~~~hdu 用c++交 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <iostream> 6 #include <queue> 7 #include <stack> 8 #include <cmath> 9 #include <set> 10 #include <algorithm> 11 #include <vector> 12 #include <map> 13 // #include<malloc.h> 14 using namespace std; 15 #define clc(a,b) memset(a,b,sizeof(a)) 16 #define LL long long 17 const int inf = 0x3f3f3f3f; 18 const double eps = 1e-5; 19 // const double pi = acos(-1); 20 const LL MOD = 9901; 21 const int N = 110; 22 23 // inline int r(){ 24 // int x=0,f=1;char ch=getchar(); 25 // while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘) f=-1;ch=getchar();} 26 // while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 27 // return x*f; 28 // } 29 int a[N]; 30 int dp[N][N]; 31 int sum[N]; 32 33 int main(){ 34 int T,n; 35 int cas=0; 36 scanf("%d",&T); 37 while(T--){ 38 scanf("%d",&n); 39 sum[0]=0; 40 for(int i=1;i<=n;i++){ 41 scanf("%d",&a[i]); 42 sum[i]=sum[i-1]+a[i]; 43 } 44 45 for(int i=0;i<=n;i++){ 46 for(int j=i+1;j<=n;j++){ 47 dp[i][j]=inf; 48 } 49 dp[i][i]=0; 50 } 51 52 for(int len=1;len<n;len++){ 53 for(int i=1;i<n;i++){ 54 int j=len+i; 55 for(int k=1;k<=j-i+1;k++){ 56 dp[i][j]=min(dp[i][j],dp[i+1][k+i-1]+dp[k+i][j]+a[i]*(k-1)+(sum[j]-sum[k+i-1])*k); 57 } 58 } 59 } 60 61 printf("Case #%d: %d\n",++cas,dp[1][n]); 62 } 63 return 0; 64 }
时间: 2024-12-19 12:21:56