洛谷每日一题——P5741 【深基7.例10】旗鼓相当的对手 - 加强版、P1048 [NOIP2005 普及组] 采药、P1208 [USACO1.3] 混合牛奶 Mixing Milk

P5741 【深基7.例10】旗鼓相当的对手 - 加强版

题目描述

【深基7.例10】旗鼓相当的对手 - 加强版 - 洛谷

运行代码

使用数组与结构体
#include<bits/stdc++.h>
using namespace std;
#define N 1005
struct node{
char ch[10];
int chinese, math, english, s;
}a[N]; 
int main(){
int n;
cin >> n;
for(int i=1; i<=n; ++i){
cin >> a[i].ch >> a[i].chinese >> a[i].math >> a[i].english;
a[i].s = a[i].chinese + a[i].math + a[i].english;
	}
	for(int i=1; i<=n; ++i){
		for(int j=i+1; j<=n; ++j){
			if(abs(a[i].chinese - a[j].chinese) <= 5 && abs(a[i].math - a[j].math) <= 5 && abs(a[i].english - a[j].english) <= 5 && abs(a[i].s - a[j].s) <= 10){
				if(strcmp(a[i].ch , a[j].ch) > 0)
					cout << a[j].ch << " " << a[i].ch << endl;
				else
					cout << a[i].ch << " " << a[j].ch << endl;
			}
		}
	}
	return 0;
}
使用向量以及字符串
  • 使用 string 类型来存储学生姓名,相比字符数组更方便操作,不需要担心数组越界等问题。
  • 使用 vector 来动态管理学生信息数组,避免了像原代码中预先定义固定大小数组可能导致的空间浪费或不够用的情况。
#include<bits/stdc++.h>
using namespace std;
#define N 1005

// 定义结构体表示学生信息
struct Student {
    string name;
    int chinese, math, english, totalScore;
};

int main() {
    int n;
    cin >> n;

    // 创建学生信息数组
    vector<Student> students(n);

    // 输入学生信息并计算总分
    for (int i = 0; i < n; ++i) {
        cin >> students[i].name >> students[i].chinese >> students[i].math >> students[i].english;
        students[i].totalScore = students[i].chinese + students[i].math + students[i].english;
    }

    // 两层循环遍历学生数组,比较符合条件的学生并输出
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            if (abs(students[i].chinese - students[j].chinese) <= 5 &&
                abs(students[i].math - students[j].math) <= 5 &&
                abs(students[i].english - students[j].english) <= 5 &&
                abs(students[i].totalScore - students[j].totalScore) <= 10) {
                if (students[i].name > students[j].name)
                    cout << students[j].name << " " << students[i].name << endl;
                else
                    cout << students[i].name << " " << students[j].name << endl;
            }
        }
    }

    return 0;
}

代码思路

  1. 输入学生信息
    • 首先通过 cin 读取学生的数量 n
    • 然后使用循环遍历,依次读取每个学生的姓名、语文成绩、数学成绩和英语成绩,并计算出每个学生三门成绩的总分。
  2. 比较学生信息
    • 通过两层嵌套的循环来遍历所有学生的组合。外层循环控制第一个学生的索引 i,内层循环控制第二个学生的索引 j,且 j 从 i + 1 开始,这样可以避免重复比较(比如已经比较过 i = 1 和 j = 2 的情况,就不需要再比较 i = 2 和 j = 1 了)。
    • 对于每一对学生 i 和 j,判断他们的语文成绩、数学成绩、英语成绩的差值绝对值是否都小于等于 5,并且总分的差值绝对值是否小于等于 10。如果满足这些条件,说明这两个学生的成绩较为接近。
    • 当满足成绩接近的条件后,再比较这两个学生的姓名。如果学生 i 的姓名字典序大于学生 j 的姓名字典序(通过 > 运算符比较 string 类型),就先输出学生 j 的姓名,再输出学生 i 的姓名;否则先输出学生 i 的姓名,再输出学生 j 的姓名。

总体来说,这段代码的目的是根据输入的学生成绩信息,找出成绩较为接近的学生对,并按照姓名字典序的顺序输出这些学生对的姓名。

P1048 [NOIP2005 普及组] 采药

题目描述

[NOIP2005 普及组] 采药 - 洛谷

运行代码

#include<iostream>
#include<algorithm>
using namespace std;

const int MAXN = 1009;
int dp[MAXN][MAXN];

int main() {
    int t, m;
    int time[MAXN], worth[MAXN];

    cin >> t >> m;

    for (int i = 1; i <= m; ++i) {
        cin >> time[i] >> worth[i];
    }

    // 初始化dp数组第一行
    for (int j = 0; j <= t; ++j) {
        if (j >= time[1]) {
            dp[1][j] = worth[1];
        }
    }

    // 动态规划计算dp数组其他行
    for (int i = 2; i <= m; ++i) {
        for (int j = 0; j <= t; ++j) {
            if (j < time[i]) {
                dp[i][j] = dp[i - 1][j];
            } else {
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - time[i]] + worth[i]);
            }
        }
    }

    cout << dp[m][t];

    return 0;
}

代码思路

这段代码解决的是一个背包问题,具体来说是一个 0/1 背包问题的变体。给定一个总时间 t 和 m 个物品,每个物品有对应的花费时间 time[i] 和价值 worth[i],要求在总时间限制内选择物品,使得所选物品的总价值最大。

  1. 数据读取与初始化

    • 首先通过 cin 读取总时间 t 和物品的数量 m
    • 然后使用循环依次读取每个物品的花费时间 time[i] 和价值 worth[i],并将这些数据存储到相应的数组中。
    • 对于 dp 数组,它是用于记录中间状态的二维数组。其中 dp[i][j] 表示在前 i 个物品中,在总时间限制为 j 的情况下能获得的最大价值。在初始化阶段,我们先单独处理了 dp 数组的第一行(即只考虑第一个物品时的情况),如果总时间 j 大于等于第一个物品的花费时间 time[1],那么 dp[1][j] 就等于第一个物品的价值 worth[1],否则为 0(因为时间不够选这个物品,价值就是 0)。
  2. 动态规划计算过程

    • 接下来通过两层嵌套的循环来填充 dp 数组的其他部分。外层循环变量 i 从 2 开始,表示考虑第 i 个物品(因为第一行已经单独初始化了),一直到 m(所有物品都考虑完)。内层循环变量 j 从 0 开始,表示总时间限制,一直到 t(给定的总时间)。
    • 在每次循环中,对于 dp[i][j] 的计算,需要判断当前总时间 j 是否小于第 i 个物品的花费时间 time[i]
      • 如果 j < time[i],这意味着在总时间限制为 j 的情况下,无法选择第 i 个物品,所以 dp[i][j] 的值就等于不考虑第 i 个物品时(即前 i - 1 个物品)在总时间限制为 j 的情况下能获得的最大价值,也就是 dp[i - 1][j]
      • 如果 j >= time[i],此时有两种选择:一是不选择第 i 个物品,那么最大价值就是前 i - 1 个物品在总时间限制为 j 的情况下能获得的最大价值,即 dp[i - 1][j];二是选择第 i 个物品,那么此时总时间就剩下 j - time[i],所以要加上第 i 个物品的价值 worth[i],即 dp[i - 1][j - time[i]] + worth[i]。我们需要取这两种情况中的最大值作为 dp[i][j] 的值,所以通过 max 函数来实现,即 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - time[i]] + worth[i])
  3. 结果输出:最后,当 dp 数组全部填充完成后,dp[m][t] 就表示在考虑了所有 m 个物品,总时间限制为 t 的情况下能获得的最大价值,将其输出即可。

综上所述,通过动态规划的方法,逐步填充 dp 数组,记录下不同物品选择情况下的最大价值,最终得到在给定条件下的最优解(即最大总价值)。

P1208 [USACO1.3] 混合牛奶 Mixing Milk

题目描述

[USACO1.3] 混合牛奶 Mixing Milk - 洛谷

运行代码

使用结构体
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
struct milk {
    int p, s;
} a[maxn];
int cmp(milk x1, milk x2) {
    if (x1.p != x2.p)
        return x1.p < x2.p;
    else {
        return x1.s > x2.s;
    }
}
int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        cin >> a[i].p >> a[i].s;
    }
    sort(a + 1, a + 1 + m, cmp);
    int sum = 0;
    for (int i = 1; i <= m; i++) {
        if (n - a[i].s >= 0) {
            n -= a[i].s;
            sum += a[i].p * a[i].s;
        } else {
            sum += a[i].p * n;
            break;
        }
    }
    cout << sum << endl;
    return 0;
}
使用数组
  • 使用 vector 来存储牛奶的信息,相比于数组更加灵活,不需要预先指定固定的最大长度,避免了可能出现的数组越界问题以及内存浪费(如果实际数据量小于预设的 maxn)。
  • 将结构体成员变量名改为更具可读性的 price(价格)和 supply(供应量)。
  • 比较函数 compare 的参数改为按值传递,这在大多数情况下是更合适的做法,并且函数体内部逻辑更加清晰,直接返回比较结果。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;

// 定义结构体表示牛奶信息
struct Milk {
    int price;
    int supply;
};

// 比较函数,用于排序
bool compare(Milk x1, Milk x2) {
    if (x1.price!= x2.price)
        return x1.price < x2.price;
    return x1.supply > x2.supply;
}

int main() {
    int n, m;
    cin >> n >> m;

    vector<Milk> milks(m);

    // 输入牛奶的价格和供应量信息
    for (int i = 0; i < m; ++i) {
        cin >> milks[i].price >> milks[i].supply;
    }

    // 对牛奶信息按照价格和供应量进行排序
    sort(milks.begin(), milks.end(), compare);

    int sum = 0;
    for (int i = 0; i < m; ++i) {
        if (n - milks[i].supply >= 0) {
            n -= milks[i].supply;
            sum += milks[i].price * milks[i].supply;
        } else {
            sum += milks[i].price * n;
            break;
        }
    }

    cout << sum << endl;

    return 0;
}

代码思路

这段代码主要解决的是一个根据给定的牛奶购买预算和不同牛奶的价格、供应量信息,来计算在预算范围内购买牛奶所能获得的最大花费的问题。

  1. 数据输入与初始化

    • 首先通过 cin 读取两个整数 n 和 m,其中 n 表示购买牛奶的预算,m 表示可供选择的牛奶种类数量。
    • 然后使用循环遍历输入每一种牛奶的价格 price 和供应量 supply,并将这些信息存储到 vector 中的 Milk 结构体对象里。
  2. 数据排序

    • 定义了一个比较函数 compare,用于对 vector 中的牛奶信息进行排序。在比较函数中,首先比较牛奶的价格,如果价格不同,就按照价格从小到大排序;如果价格相同,再比较供应量,按照供应量从大到小排序。这样排序的目的是为了在后续购买牛奶时,优先选择价格低且供应量相对较大的牛奶,以便在预算范围内获得更大的花费。
    • 通过 sort 函数结合 compare 函数对 vector 中的牛奶信息进行排序。
  3. 购买牛奶并计算花费

    • 初始化一个变量 sum 用于记录购买牛奶的总花费。
    • 通过循环遍历已经排序好的牛奶信息。在每次循环中,判断当前预算 n 是否足够购买当前种类牛奶的全部供应量:
      • 如果 n - milks[i].supply >= 0,说明预算足够购买该种牛奶的全部供应量,那么就从预算中减去购买该种牛奶所花费的量(即该种牛奶的供应量),并将购买该种牛奶的花费(价格乘以供应量)累加到 sum 中。
      • 如果 n - milks[i].supply < 0,说明预算不够购买该种牛奶的全部供应量,此时只能用剩余的预算按当前牛奶的价格购买部分牛奶,将购买部分牛奶的花费(价格乘以剩余预算)累加到 sum 中,并通过 break 语句跳出循环,因为预算已经用完,无法再购买其他牛奶了。
  4. 结果输出:最后,将计算得到的购买牛奶的总花费 sum 通过 cout 输出。

综上所述,该代码通过对牛奶信息进行排序,然后按照排序后的顺序在预算范围内合理购买牛奶,最终计算出在给定预算下购买牛奶所能获得的最大花费。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筱姌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值