uva 714 Copying Books

//真背背啊,,以前做过这个题,,当时不会,弄半天是个经典的"最大值最小化"问题,,主要出错在忘判左右界了,

//比如1000000 1 1 1分3份得时候 要注意左界; 1 2 3 4 5 分成5分的时候时候要注意右界

//得到的经验就是 如果当找不到code 的bug 时候,考虑边界情况,,数据的边界或者极限值可能是根救命稻草哟哟哟哟哟哟哟

#include <iostream> #include <string> #include <map> #include <vector> #include <memory.h> #include <cstdio> #include <cmath> #include <stack> #include <algorithm> using namespace std; const long long MAX=505,INF=1<<30; long long m,k,a[MAX],sum; stack<long long> ans; bool tryIt(const long long &Sum){ long long s=0,splash=0; for(long long i=m-1;i>=0;i--){ if(i>=(k-1)-splash&&s+a[i]<=Sum){ s+=a[i]; } else{ s=a[i]; if(i==m-1||s>Sum) return 0;//注意右边界 ++splash; } } if(s>Sum) return 0;//注意左边界 return splash==k-1; } long long bsearch(){ long long l=0,r=sum+1,m; while(l<r){ m=l+(r-l)/2; if(tryIt(m)) r=m; else l=m+1; } return l; } int main() { freopen("i.txt","r",stdin); //freopen("castle.in","r",stdin); //freopen("castle.out","w",stdout); long long s,nCase,p,splash; cin>>nCase; while(nCase--){ while(!ans.empty()) ans.pop(); sum=0; cin>>m>>k; for(long long i=0;i<m;i++){ cin>>a[i]; sum+=a[i]; } p=bsearch(); //cout<<p<<endl; s=0; splash=0; for(long long i=m-1;i>=0;i--){ if(i>=(k-1)-splash&&s+a[i]<=p){ s+=a[i]; } else{ s=a[i]; ans.push(i); ++splash; } } for(long long i=0;i<m;i++){ if(i) cout<<" "; cout<<a[i]; if(!ans.empty()&&i==ans.top()){ cout<<" /"; ans.pop(); } } cout<<endl; } return 0; }

一个dp的方法:

设dp[i,j]表示前j个人复制前i本书所需要的最少时间,有状态转移方程dp[i,j]=min(dp[i,j],max(dp[v,j-1],sum[v+1,i])),其中1<=i<=m,1<=j<=k,j-1<=v<=i-1,sum[v+1,j]表示第v+1本书到第i本书的页数之和。
http://www.cppblog.com/mythit/archive/2009/06/16/87770.html

你可能感兴趣的:(books)