标签:des blog http os io ar for 数据 div
http://tyvj.cn/Problem_Show.aspx?id=1359
一开始是一眼看出是二分的,因为这里有单调性,因为取钱是一次取完并且是连续的。
所以最优取法就是准备达到某个价值再取。最优里边包含了次优,也就是取不到m次我就能取完就一定能够取m次能够取完,只要在取法那里随便取就行了,保证不超过这个某个价值
于是我们可以二分这个价值,看看能不能最优法取完并且次数小于m。
#include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> using namespace std; #define rep(i, n) for(int i=0; i<(n); ++i) #define for1(i,a,n) for(int i=(a);i<=(n);++i) #define for2(i,a,n) for(int i=(a);i<(n);++i) #define for3(i,a,n) for(int i=(a);i>=(n);--i) #define for4(i,a,n) for(int i=(a);i>(n);--i) #define CC(i,a) memset(i,a,sizeof(i)) #define read(a) a=getint() #define print(a) printf("%d", a) #define dbg(x) cout << #x << " = " << x << endl #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; } inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<‘0‘||c>‘9‘; c=getchar()) if(c==‘-‘) k=-1; for(; c>=‘0‘&&c<=‘9‘; c=getchar()) r=r*10+c-‘0‘; return k*r; } inline const int max(const int &a, const int &b) { return a>b?a:b; } inline const int min(const int &a, const int &b) { return a<b?a:b; } const int N=100005; int n, m, a[N]; inline const bool check(const int &x) { int sum=0, t=0, i; for(i=1; i<=n; ++i) { sum+=a[i]; if(sum>x) sum=a[i], ++t; if(t>=m) return 0; //这里要注意,因为此时一定还有没取完的,所以==m的时候就要退出了 } return 1; } int main() { read(n); read(m); int mx=0, sum=0; for1(i, 1, n) { read(a[i]); mx=max(mx, a[i]); sum+=a[i]; } int l=mx, r=sum, mid; while(l<=r) { mid=(l+r)>>1; if(check(mid)) r=mid-1; else l=mid+1; } print(r+1); return 0; }
因为范围很大,所以我们二分的范围要适当做点技巧。
7 5
100
400
300
100
500
101
400
500
【样例说明】
采取下面的方案可以使每次领到的工资不会多于500。这个答案不能再少了。
100 400 300 100 500 101 400 每一天的薪水
<------1 <-------2 <---3 <---4 <---5 领取工资的时间
500 400 500 101 400 领取到的工资
标签:des blog http os io ar for 数据 div
原文地址:http://www.cnblogs.com/iwtwiioi/p/3942145.html