[bzoj1700]: [Usaco2007 Jan]Problem Solving 解题

  不能贪心!不能贪心!不能贪心!

  反正有反例(有的题目月初支付款很少,月末支付款很大,和前面的题凑到一个月的话可能导致下个月写不了= =这时放后一个月,和后面的题一起开始写可能更优)

  比如:

50 4
40 1
5 10
43 30
1 10

  老老实实DP吧。。。f[i][j]表示在第i月过后,共解决了j道题,第i月结余(可用于下个月的月初支付)的最大值。cost0[]、cost1[]分别表示月初支付和月末支付

  f[i][j]=max{m-sum(cost1[k+1]....cost1[j])},(前提是sum(cost0[k+1]....cost0[j])<=f[i-1][k]且sum(cost1[k+1]....cost1[j])<=m)。

  数组滚动一下。。。时间复杂度O(P^3)

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=305;
 6 int a[maxn],b[maxn],prea[maxn],preb[maxn];
 7 short f[2][maxn];
 8 int i,j,k,n,m,pre,now,nowrest,next,s1,s2,ans;
 9 bool flag;
10  
11 int ra;char rx;
12 inline int read(){
13     rx=getchar();ra=0;
14     while(rx<'0'||rx>'9')rx=getchar();
15     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
16 }
17 int main(){
18     m=read();n=read();
19     for(i=1;i<=n;i++)a[i]=read(),b[i]=read(),prea[i]=prea[i-1]+a[i],preb[i]=preb[i-1]+b[i];
20     nowrest=m;ans=1;
21     memset(f[1],255,(n+1)<<1);f[1][0]=m;pre=1;now=0;
22     while(1){
23         ans++;
24         memset(f[now],255,(n+1)<<1);
25         for(i=0;i<=n;i++){
26             flag=0;
27             for(j=i;j>=0&&preb[i]-preb[j]<=m;j--)
28                 if(prea[i]-prea[j]<=f[pre][j]){f[now][i]=m-preb[i]+preb[j];flag=1;break;}
29             if(!flag)break;
30         }
31         if(i>n)break;
32         swap(now,pre);
33     }
34     printf("%d
",ans+1);
35     return 0;
36 }
View Code
原文地址:https://www.cnblogs.com/czllgzmzl/p/5068024.html