冉文的烦恼
【问题描述】
冉文是个粗心的人,经常不小心把垃圾丢到地上。艾教实在没办法,只好派了m个学生,去捡冉文走过路上的垃圾。
假设冉文走过的路线是一条直线,每个位置分别是1..n,每个位置上垃圾的个数是ai。所有学生起始位置都在0,每秒钟,他们有两种选择:
1.向右走一步。
2.捡起一个地上的垃圾。
现在我们的问题是:要捡起冉文的所有垃圾,最少需要多少秒?
【输入格式】
第一行输入两个正整数n,m,如题目所述。
第二行输入n个非负整数ai,代表每个位置的垃圾个数。ai<=10^9
【输出格式】
一个数字,表示最少的时间。
【输入样例】
3 2
1 0 2
【输出样例】
5
解释:第一个学生走到3,然后捡2个垃圾,共花费时间5,第二个学生走到1,捡1个垃圾,共花费时间2。
【数据范围与约定】
对于30%的数据,m=1。
对于另30%的数据,m=2,垃圾总个数<=21。
对于100%的数据,n,m<=100000
【个人想法】
二分答案,因为每个点都小于10^9,所以下界0,上界为n*10^9
然后贪心(算是吧)
一个人先从起点往后捡,然后自己时间完了的时候让下一个人继续刚才的位置再往后捡,如果超过m个人时就不行,return,如果至尾也都没超m个人,就行。
【题解代码】
第一个是自己写的,交上去后re,结果是a[1000005]写成了a[100005]...
改了后90分,因为上界应该是1000000000*n,我又少数了个0,成了100000000*n。。。
有点想死。。。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
typedef long long ll;
ll n,m;
ll a[1000005];
bool can(ll lim)
{
//cout<<lim<<"????"<<endl;
ll op=lim;
ll kl=1;
ll k=0;
for(ll i=1;i<=n;i++)
{
op-=1;
if(op>=a[i])
op-=a[i];
else
{
k=a[i]-op;
op=0;
}
if(i==n&&k<=0)
break;
if(op==0)
{
kl++;
op=lim-i-k;
}
while(op<0)
{
kl++;
op+=lim-i;
if(lim-i<=0)
return 0;
}
k=0;
}
if(kl<=m)
return 1;
else
return 0;
}
int main()
{
freopen("ranwen.in","r",stdin);
freopen("ranwen.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
for(ll i=n;i>=1;i--)
{
if(a[i]==0)
{
n--;
}
else
{
break;
}
}
ll l=0,r=1000000000*n;
while(l+1<r)
{
ll mid=(l+r)/2;
if(can(mid)==1)
r=mid;
else
l=mid+1;
}
if(can(r-1)&&r>0)
r-=1;
cout<<r;
}
第二个是教练给的
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
long long int n, m, a[100005];
bool check(long long int t){
long long int um = m, extra = 0;
for (int i=0;i<n;i++){
if (um >= a[i]/t) um -= a[i]/t;
else return false;
if (extra >= a[i]%t) extra -= a[i]%t;
else if (um){
extra += t - a[i]%t;
um--;
}
else return false;
if (!--t){
for(int j=i+1;j<n;j++)
if (a[j])return false;
return true;
}
if (extra)extra--;
}
return true;
}
int main(int argc,char **argv)
{
// argv[2]鏄枃浠跺悕
freopen(argv[2],"r",stdin);
char ch[20]="ranwen0.out";
ch[6]=argv[2][6];
freopen(ch,"w",stdout);
scanf("%lld%lld",&n,&m);
for (int i=0;i<n;i++)
scanf("%lld",a+i);
long long int ub = 2000000000000000, lb = 0;
while (ub-lb-1){
long long int mid = (ub+lb)/2;
if (check(mid)) ub = mid;
else lb = mid;
}
cout<<ub+1<<endl;
}
后面的这个应该靠谱些。。