您的位置:首页 > 其它

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

2015-12-22 20:33 253 查看
  不能贪心!不能贪心!不能贪心!

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

  比如:

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)

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=305;
int a[maxn],b[maxn],prea[maxn],preb[maxn];
short f[2][maxn];
int i,j,k,n,m,pre,now,nowrest,next,s1,s2,ans;
bool flag;

int ra;char rx;
inline int read(){
rx=getchar();ra=0;
while(rx<'0'||rx>'9')rx=getchar();
while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
}
int main(){
m=read();n=read();
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];
nowrest=m;ans=1;
memset(f[1],255,(n+1)<<1);f[1][0]=m;pre=1;now=0;
while(1){
ans++;
memset(f[now],255,(n+1)<<1);
for(i=0;i<=n;i++){
flag=0;
for(j=i;j>=0&&preb[i]-preb[j]<=m;j--)
if(prea[i]-prea[j]<=f[pre][j]){f[now][i]=m-preb[i]+preb[j];flag=1;break;}
if(!flag)break;
}
if(i>n)break;
swap(now,pre);
}
printf("%d\n",ans+1);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: