CSDN第30期周赛

1、题目名称:天然气订单
天然气运输成本昂贵,危险性高,为了节省运输成本,提倡绿色环保,需要尽可能的优化订单配送,比如相同地区的天然
气订单可以一次性配送。 现需要向多个地区运输天然气。但是同一个地区可能有多个订单需求。当前仅只知道某些成对的
订单是同一个地区的,同一个地区的天然气需要尽可能一次性配送从而降低运输成本,所以需要尽可能的将同一个地区的。订单放在一起。订单的编号是1到n。 

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int MAXN = 10010;
int n, m, cnt = 0;
vector<int> G[MAXN];
bool vis[MAXN] = {false};
void bfs(int u, vector<int>& v) {
queue<int> q;
q.push(u);
v.push_back(u);
vis[u] = true;
while (!q.empty()) {
int x = q.front();
q.pop();
for (int i = 0; i < G[x].size(); ++i) {
int y = G[x][i];
if (!vis[y]) {
q.push(y);
vis[y] = true;
v.push_back(y);
}
}
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < m; ++i) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
vector<vector<int>> ans;
for (int i = 1; i <= n; ++i) {
if (!vis[i]) {
vector<int> v;
bfs(i, v);
ans.push_back(v);
++cnt;
}
}
cout << cnt << endl;
sort(ans.begin(), ans.end(), [](vector<int> a, vector<int> b) {
return a[0] < b[0];

});
for (auto& v : ans) {
sort(v.begin(), v.end());
for (int i = 0; i < v.size(); ++i) {
cout << v[i];
if (i < v.size() - 1) {
cout << " ";
}
}
cout << endl;
}
return 0;
}

实现一个图的遍历和连通块的查找,目的是将相同地区的订单放在一起,从而降低天然气的运输成本。具体来说,首先读入天然气订单的数量n和订单之间的联系m,接下来用vector数组G来存储订单之间的联系,然后利用bfs算法进行图的遍历,将同一地区的订单放在一个vector中,并将其存储在ans数组中。最后,对于所有的连通块,按照第一个元素排序,并对每个连通块中的元素进行排序输出,输出结果为每个连通块的订单编号。

具体而言,代码的核心步骤为:

  1. 读入订单数量n和联系数量m
  2. 使用vector数组G存储订单之间的联系
  3. 对于每个订单i,如果它还没有被遍历过,就进行一次BFS遍历,将所有与它相连的订单都放在同一个vector中,并将该vector存储在ans数组中
  4. 输出ans数组,按照每个连通块的第一个元素进行排序,并对每个连通块中的元素进行排序输出

值得注意的是,这段代码没有对连通块进行编号,只是通过输出每个连通块的订单编号来表示它们是同一地区的订单。如果需要对连通块进行编号,可以在bfs函数中添加一个计数器,记录遍历过的连通块数量,然后将该计数器的值输出即可。

2、题目名称:小艺读书
书是人类进步的阶梯。 小艺每周因为工作的原因会选择性的每天多读几页或者少读几页。 小艺想知道一本n页的书她会在周几读完。

#include <iostream>
using namespace std;
#include <string>
#include <vector>
int n,a[10],i;
int main(){
cin>>n;
for(i=1;i<=7;i++)cin>>a[i];
for(i=1;;i++){
n-=a[(i-1)%7+1];
if(n<=0)break;
}
cout<<(i-1)%7+1<<endl;
return 0;
}

求解小艺读书的问题,这段代码首先读入书的页数n和小艺每周的读书计划a1~a7,其中a1表示周一读书的页数,a2表示周二读书的页数,以此类推。接下来通过一个循环来模拟小艺的读书过程。在每次循环中,先将n减去当前需要读的页数a[(i-1)%7+1],其中(i-1)%7+1是为了保证a数组在循环中循环使用。如果n小于等于0,则说明小艺已经读完了这本书,此时退出循环。最后输出(i-1)%7+1,即为小艺在周几读完这本书。需要注意的是,这段代码的实现方式比较简单,只适用于a数组比较小的情况。如果a数组很大,可能会出现计算超时的问题。此时可以考虑使用更高效的算法来求解该问题,例如递归、动态规划等算法。

3、题目名称:买苹果
小易去附近的商店买苹果,奸诈的商贩使用了捆绑交易,只提供6个每袋和8个每袋的包装(包装不可拆分)。 可是小易现在只想购买恰好n个苹果,小易想购买尽量少的袋数方便携带。如果不能购买恰好n个苹果,小易将不会购买。

#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int a = -1;
for (int i = 0; i <= n/6; i++) {
for (int j = 0; j <= n/8; j++) {
if (6*i + 8*j == n) {
if (a == -1 || a > i+j) {
a = i+j;
}
}
}
}
cout << a << endl;
return 0;
}

解决小易买苹果的问题,商贩只提供6个每袋和8个每袋的包装,小易要买恰好n个苹果,且要尽量少的袋数。代码采用了暴力枚举的方式,在i表示6个每袋的数量,j表示8个每袋的数量的情况下,判断是否满足小易要买的n个苹果,若满足,则计算出袋数,与当前最小袋数进行比较并更新最小袋数a。最后输出a即可。

4、题目名称:圆桌
有N个客人与足够多张的圆桌。主人安排每位客人坐在一个圆桌边,但是每位客人希望自己左右边上分别有一些空座位,不然会觉得害羞。注意,如果一个客人所在的圆桌只有他一个人,那么他左边的空座位数量就是他右边的空座位数量。 试问主人需要准备多少个座位,才能让每个客人舒适的坐下。

考完之后上网查了一下,应该是先将每个客人要求的左右空座位数量都减去 “1”(因为每个圆桌初始时已经有两个座位),得到一个新的要求数组 “p”。然后从“1”到 “N”枚举每个圆桌,对于第 “i” 个圆桌,它的两侧需要的空座位数量就是 “p_i“ 和 “p_{i+1}”(其中 “p_{N+1}=p_1”)。为了满足这两个要求,我们可以将该圆桌两侧的座位数设置为 “\max(p_i,p_{i+1})+1”,这样既满足了左侧要求,又满足了右侧要求,并且增加的座位数是最少的。最后统计所有圆桌的座位数之和即为答案。很可惜没写出来。

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

int main() {
    int N;
    cin >> N;
    vector<int> p(N);
    for (int i = 0; i < N; i++) {
        cin >> p[i];
        p[i]--; // 每位客人要求的左右空座位数量减 1
    }
    int ans = 0;
    for (int i = 0; i < N; i++) {
        int seats = max(p[i], p[(i+1)%N]) + 1; // 该圆桌两侧需要的空座位数量
        ans += seats;
    }
    cout << ans << endl;
    return 0;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值