最少开垦时间设为i,他的范围应该是k(开垦一块区域的最少时间)到nowMost(不用任何资源的最短开垦时间)
思路:对所有开垦时间大于i的土地使用资源,使之开垦时间为i,如果资源m够所有的土地开垦时间等于或小于i,则i就是最短开垦时间
七十分:
#include<iostream>
/*
#include<cmath>
#include<cstring>
#include<string>
#include<string.h>
#include<stdio.h>
#include<algorithm>*/
using namespace std;
int main()
{
int n;//n块地
int m;//m的资源
int k;//最少可能天数
int t[101];//开垦需要天数
int c[101];//减少一天需要资源
cin>>n>>m>>k;
int nowMost=0;//记录不用资源而开发所需的最长时间
for(int i=0;i<n;i++)
{
cin>>t[i];
cin>>c[i];
if(t[i]>nowMost) nowMost=t[i];
}
int Least=nowMost;//最少天数从k一直加加直到资源可以满足
int nowR=m;//目前剩下的资源
int flag=1;//代表资源足够
for(int i=k;i<nowMost;i++)//第一个满足条件的i即是最短开垦时间
{
flag=1;//
nowR=m;
for(int j=0;j<n;j++)//对每一块地分配资源使之完成时间均为i,看看资源能否满足,能则i是最少开垦时间
{
if(t[j]>i)//只有本来的开垦时间比较大的才需要资源来减少时间
{
nowR -=c[j]*(t[j]-i);
if(nowR<0)
{
flag=0;//资源不够,最少开垦时间不能为i
break;
}
}
}
if(flag==1&&Least>i) //
{
Least=i;
break;///可以得到最短时间
}
}
cout<<Least;
return 0;
}
优化:使用二分法,根据中间点能否满足条件动态的设置判断的数据范围
#include<iostream>
#include <bits/stdc++.h>
using namespace std;
int t[100001];//开垦需要天数
int c[100001];//减少一天需要资源
bool FindMin(int s,int e,int t[],int c[],int m,int n1)//s--e代表可能的完成时间
{
int flag=1;
int nowR=m;
int n=n1;
for(int j=n-1;j>=0;j--)
{
if(t[j]>(s+e)/2)//判断中间的时间能不能满足条件
{
nowR -=c[j]*(t[j]-(e+s)/2);
if(nowR<0)
{
flag=0;//资源不够,最少开垦时间不能为i
return false;
}
}
}
return true;
}
int main()
{
int n;//n块地
int m;//m的资源
int k;//最少可能天数
cin>>n>>m>>k;
int nowMost=0;//记录不用资源而开发所需的最长时间
for(int i=0;i<n;i++)
{
cin>>t[i];
cin>>c[i];
if(t[i]>nowMost) nowMost=t[i];
}
int l=k;
int r=nowMost;
while(l<=r)//根据中间时间是否能满足条件动态的设置判断范围最终找到一个最小时间
{
if(FindMin(l,r,t,c,m,n))//时间可以小一点
r=((r+l)/2)-1;
else l=((r+l)/2)+1; //时间要大一点
}
cout<<l;
return 0;
}