第一思路是枚举,即枚举所有可能的最小耗时,计算每个耗时的所需资源,如果资源不够了,输出当前最小耗时+1即可
#include<iostream> using namespace std; int n,m,k; typedef struct Node{ int t,c; }Node; Node arr[100005]; int all_need=0; int time_need=-1; int main(){ cin>>n>>m>>k; for(int i=0;i<n;i++){ cin>>arr[i].t>>arr[i].c; all_need+=(arr[i].c*(arr[i].t-k)); time_need=max(time_need,arr[i].t); } if(m>=all_need){//资源是否足够支付将所有区域所需时间降到k cout<<k<<endl; }else{ int ans=0; for(int i=time_need-1;i>=k;i--){//让所有区域所需时间减少到<=i int temp=0; for(int j=0;j<n;j++){ if(arr[j].t>i){//所需天数>希望天数 temp+=(arr[j].c*(arr[j].t-i)); if(temp>m)break;//资源不够 } } if(temp>m){ ans=i+1;//天数+1即答案 break; } } cout<<ans<<endl; } return 0; }
当然这里使用了嵌套for循环,时间复杂度为O(n^2),因此只能拿到70分
因此我们需要尝试优化,仔细观察不难发现可以优化的点就在于“枚举希望耗时”,我们可以将线性枚举耗时i,优化为二分枚举耗时i,这样时间复杂度就变为nlogn了即可满分
#include<iostream> #include<algorithm> using namespace std; int n,m,k; typedef struct Node{ int t,c; }Node; Node arr[100005]; int time_need=-1; bool check(int time){ int sum=0;//计算所有区域耗时降到time需要的资源 for(int i=0;i<n;i++){ if(arr[i].t<time)continue;//已经比time小了 sum+=(arr[i].c*(arr[i].t-time)); if(sum>m)return false; } return true; } int main(){ cin>>n>>m>>k; for(int i=0;i<n;i++){ cin>>arr[i].t>>arr[i].c; time_need=max(time_need,arr[i].t); } //尝试在枚举“希望耗时 ”这里进行二分优化 int left=k,right=time_need; while(left<=right){ int mid=(left+right)/2; if(check(mid)){//判断是否所有区域耗时都能达到mid right=mid-1;//尝试更小 }else{ left=mid+1; } } cout<<left<<endl; return 0; }
满分思路扩展参考自
- 70分思路是对每一个区域单独处理,仔细分析后,发现可以对同一基础耗时的区域同时处理
- 单独开一个数组
sa
用来记录同一基础耗时的区域所需资源总数- 从
mx
到k
依次处理,每次使得最大基础耗时的区域同时减少一天#include <iostream> #include <algorithm> using namespace std; const int N = 1e5+10; int n,m,k; int t[N],c[N]; int sa[N];//记录同一基础耗时缩减一天所需要的总资源 int mx;//记录基础耗时的最大值 int main() { cin>>n>>m>>k; for(int i=1;i<=n;i++) { cin>>t[i]>>c[i]; sa[t[i]]+=c[i];//记录同一基础耗时缩减一天所需要的总资源 mx = max(mx,t[i]); } int ans = mx;//记录结果 for(int i=mx;i>=k;i--) { if(sa[ans]>m)break; m-=sa[ans];//同一基础耗时的同时减少一天 sa[ans-1]+=sa[ans];//下一天的需要加上上一天的资源总数 //ans的最小值为k if(ans>k) { ans--; } } cout<<ans<<endl; return 0; }
该思路单看代码可能难以理解,建议自己调试一遍
CCF-CSP 202303-2 垦田计划
于 2023-05-11 12:06:26 首次发布