题意:题意就是给你一些栅栏,每一个栅栏有一个高度h[i],你有n单位的 红和绿颜料,每隔一高度为h[i]的栅栏需要h[i]的燃料。但是有一 个限制,红颜料不能超过a,绿颜料不能超过b,问你最少需要多少颜 料能够涂满所有的栅栏。
这道题倒是不怎么难想,你用三位dp,dp[i][j][k]来表示,其中i是当前是那个栅栏,j是红颜料的次数,k是这次准备选那个颜料,那么这个状态的完整定义就是在当前栅栏用了多少红颜料并且这次可以选那个燃料,
然后我一直卡在了怎么确定绿颜料的使用,然后可以发现可以维护一个前缀和,减去绿颜料就可以等到红颜料!然后我就一直卡着了。
接下来是代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int inf=1e7+100; 4 int n; 5 int num[220]; 6 int dp[220][40500][2]; 7 int a,b,all=0; 8 int main(){ 9 freopen("input.txt","r",stdin); 10 freopen("output.txt","w",stdout); 11 scanf("%d",&n); 12 scanf("%d%d",&a,&b); 13 for(int i=1;i<=n;i++) scanf("%d",&num[i]); 14 for(int i=0;i<=n;i++) 15 for(int j=0;j<=40100;j++) 16 for(int g=0;g<2;g++) 17 dp[i][j][g]=inf; 18 dp[0][0][0]=0;dp[0][0][1]=0; 19 for(int i=1;i<=n;i++){ 20 all+=num[i]; 21 for(int j=0;j<=min(all,a);j++){ 22 if(all-j<=b) dp[i][j][1]=min(dp[i-1][j][1],dp[i-1][j][0]+min(num[i],num[i-1])); 23 if(j+num[i]<=a&&j+num[i]<=all) dp[i][j+num[i]][0]=min(dp[i-1][j][0],dp[i-1][j][1]+min(num[i],num[i-1])); 24 } 25 } 26 int ans=inf; 27 for(int i=0;i<=a;i++) ans=min(ans,min(dp[n][i][0],dp[n][i][1])); 28 if(ans==inf) ans=-1; 29 printf("%d\n",ans); 30 return 0; 31 }