【CCF CSP】202303-2 垦田计划

文章比较了C++中使用`vector`和`map`解决资源分配问题的代码,指出map在处理这类问题时虽然简洁但效率较低。作者还强调了初始化和数据结构对性能的影响,以及int数组默认值的重要性。
摘要由CSDN通过智能技术生成

1. 题目要求

在这里插入图片描述

2. 前提

3. 思想

3. 代码

!!瑕疵代码-70分!!

#include <iostream>
#include <math.h>
#include <iomanip>
#include <vector>
#include <algorithm>
using namespace std;
/**
基础耗时 arr1[i]
缩减一天所需资源 arr2[i]
c投入资源数量
*/
int main(){
    int n,m,k;
    int temp1,temp2;
    cin >> n >> m >>k;
    //vector<vector<int>> arr(2,vector<int>(n));
    vector<int> arr1(n);
    vector<int> arr2(n);
    for(int i = 0; i < n; i++){
        cin >> arr1[i] >> arr2[i];

    }
/**下面这个循环写的太丑陋了,导致超时*/
    while(m>0){
        //找到最大的基础耗时
        int max_num = *max_element(arr1.begin(),arr1.end());
        bool flag = true;
        for(int i = 0; i < n; i++){
            if(max_num == arr1[i]){
                if(m>=arr2[i]&&arr1[i]>=k+1){
                    m-=arr2[i];
                    arr1[i]-=1;
                    flag = false;
                }
            }
        }
        if(flag)
            break;
    }
    int min_num = *max_element(arr1.begin(),arr1.end());
    cout << min_num <<endl;
    return 0;
}

正确代码1:vector date(maxn);

#include <iostream>
#include <math.h>
#include <iomanip>
#include <vector>
#include <algorithm>
using namespace std;
/**
n-待开垦的区域总数
m-顿顿手上的资源数量
k-每块区域的最少开垦天数
*/
//2.3e5=2.3*10^5;
int main(){
    int n,m,k;
    int maxtime=0;
    const int maxn=1e5+10; //1*10^5+10 = 100010
    //因为全部数据小于等于10^5=100000
    /*int最大值2147483647 > 2*10^9
      m<=10^9,所以int m;*/
    cin >> n >> m >>k;
    vector<int> arr1(n);//基础耗时(第i块区域开垦耗时)
    vector<int> arr2(n);//第i块区域耗时缩减一天所需资源
    vector<int> date(maxn);//从i天缩短一天所需的资源

    for(int i = 0; i < n; i++){
        cin >> arr1[i] >> arr2[i];
        //初始化从i天缩短一天所需的资源数
        date[arr1[i]] += arr2[i];//date[arr1[i]] 默认值为0
        //记录目前的最大耗时
        maxtime = max(maxtime,arr1[i]);
    }
    int ans = k;
    //从最大耗时开始逐次降低耗时
    //直到现有的资源无法再缩短一天 或 已缩短到最少开垦天数
    for(int i = maxtime; i > k; i--){
        if(m>=date[i]){
            //将被缩短天数所需的资源加到前一天
            date[i-1] += date[i];
            m -= date[i];
        }else{
            //现有的资源无法再缩短一天,此时的i即为最少开垦天数
            ans = i;
            break;
        }
    }
    cout << ans <<endl;
    return 0;
}


正确代码2: map<int,int> date;

#include <iostream>
#include <math.h>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
/**
n-待开垦的区域总数
m-顿顿手上的资源数量
k-每块区域的最少开垦天数
*/
int main(){
    int n,m,k;
    int maxtime=0;

    cin >> n >> m >>k;
    vector<int> arr1(n);//基础耗时(第i块区域开垦耗时)
    vector<int> arr2(n);//第i块区域耗时缩减一天所需资源
    map<int,int> date;//从i天缩短一天所需的资源

    for(int i = 0; i < n; i++){
        cin >> arr1[i] >> arr2[i];
        //初始化从i天缩短一天所需的资源数
        date[arr1[i]] += arr2[i];//date[arr1[i]] 默认值为0
        //记录目前的最大耗时
        maxtime = max(maxtime,arr1[i]);
    }
    int ans = k;
    //从最大耗时开始逐次降低耗时
    //直到现有的资源无法再缩短一天 或 已缩短到最少开垦天数
    for(int i = maxtime; i > k; i--){
        if(m>=date[i]){
            //将被缩短天数所需的资源加到前一天
            date[i-1] += date[i];
            m -= date[i];
        }else{
            //现有的资源无法再缩短一天,此时的i即为最少开垦天数
            ans = i;
            break;
        }
    }
    cout << ans <<endl;
    return 0;
}

输入:
4 9 2
6 1
5 1
6 2
7 1
执行完第一个for循环后,
date = { {5,1}, {6,3}, {7,1} }
maxtime = 7
执行第二个for循环时:
i = 7; m = 9; date[7] = 1; date[6] = 1+3 = 4; m=8;
i = 6; m = 8; date[6] = 4; date[5] = 4+1 = 5; m= 4;
i = 5; m = 4; date[5] = 5; 由于m<date[5],所以ans = 5; break;
最后输出5。

4. 结果

在这里插入图片描述
没想到用map 反而比int date[maxn]慢且占的空间大。

5. 总结

int数组声明在函数中,未初始化时值未定义。

int数组声明成全局或static, 未初始化值默认是0.
vector变量初始值默认为0;
map<int,int>新增一项时,其value(second)值默认为0.
所以 ate[arr1[i]] += arr2[i]; 这一句可以成立。

6. 参考代码

https://blog.csdn.net/weixin_53919192/article/details/131490410
https://blog.csdn.net/CXR_XC/article/details/130174654

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值