打卡信奥刷题(2807)用C++实现信奥题 B4093 [CSP-X2021 山东] 发送快递
题目摘要:B4093 [CSP-X2021 山东] 发送快递 本题要求将n本不同重量的书打包成快递包裹,每个包裹不超过m公斤。输入包括书的数量n、最大重量m、各书重量、必须打包的s组书(s=0时无限制)。输出最少快递件数。样例1展示了3件快递的解法,样例2展示了4件快递的解法。数据范围:n≤23,ai≤100,s≤15。解题思路包括处理必须打包的组,剩余书按重量排序,使用DFS搜索最优组合。C++
B4093 [CSP-X2021 山东] 发送快递
题目背景
原题为错题,不可做。数据范围修改如下,请以题目背景中的为准:
【数据范围和限制】
对于 40%40\%40% 的数据,1≤n≤231 \leq n \leq 231≤n≤23,1≤ai≤1001 \leq a_i \leq 1001≤ai≤100,s=0s=0s=0,mmm 的值保证有解。
对于 100%100\%100% 的数据,1≤n≤231 \leq n \leq 231≤n≤23,1≤ai≤1001 \leq a_i \leq 1001≤ai≤100,0≤s≤150 \leq s \leq 150≤s≤15,mmm 的值保证有解。
为了防止无意义的钻牛角尖的 hack,本题认为 mmm 不超过 231−12^{31}-1231−1。
题目描述
小华有 nnn 本不同的书(编号为 1,2,3,…,n1,2,3,\dots,n1,2,3,…,n),重量分别是 a1,a2,…,ana_1,a_2,\dots,a_na1,a2,…,an 公斤(重量可以相同)。他想把这些书以快递的方式发给自己的好朋友,要求每个包裹的重量不能超过 mmm 公斤(可以等于 mmm 公斤),并且小华想把其中一些书(一组书,用书的编号给出来)放在一个包裹里,应该如何打包才能使得快递件数最少。
输入格式
第一行,包含两个整数 n,mn,mn,m,之间用一个空格隔开,分别表示书的数量和快递包裹的最大重量。
第二行 nnn 个整数 aia_iai,表示 nnn 本书的重量,每两个整数之间用一个空格隔开。
第三行一个整数 sss,表示一共有 sss 组书(每组书需要打包在一起)。如果 s=0s=0s=0,则无此限制。数据保证每组书的重量不超过 mmm。
第四行开始共 sss 行,每行若干个整数,表示必须放在一个包裹里的书的编号,每两个整数之间用一个空格隔开。
输出格式
输出文件一行,一个整数,即快递最少件数。
输入输出样例 #1
输入 #1
5 10
8 4 8 2 5
0
输出 #1
3
输入输出样例 #2
输入 #2
10 80
49 11 44 18 28 24 19 10 27 29
2
1 5
4 8 2
输出 #2
4
说明/提示
【输入输出样例 1 说明】
第 111 本和第 444 本打包,重量是 101010 公斤。第 222 本和第 555 本打包,重量是 999 公斤。第 333 本单独打包,重量是 888 公斤。所以一共 333 件快递。
【输入输出样例 2 说明】
第 111 本和第 555 本打包,第 222 本、第 444 本、第 888 本和第 101010 本打包,第 333 本和第 777 本打包,第 666 本和第 999 本打包。所以一共 444 件快递。
【数据范围和限制】
对于 40%40\%40% 的数据,1≤n≤1051 \leq n \leq 10^51≤n≤105,1≤ai≤1001 \leq a_i \leq 1001≤ai≤100,s=0s=0s=0,mmm 的值保证有解。
对于 100%100\%100% 的数据,1≤n≤1051 \leq n \leq 10^51≤n≤105,1≤ai≤1001 \leq a_i \leq 1001≤ai≤100,0≤s≤1000 \leq s \leq 1000≤s≤100,mmm 的值保证有解。
C++实现
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,s,ans=54,c[55],b[55],a[55],r,lst,p,k;
vector<int> G[55];
bool vis[55];
void build(int now){
vis[now]=1;
a[p]+=b[now];
for(int i:G[now]){
if(!vis[i]) build(i);
}
}
bool cmp(int a,int b){
return a>b;
}
void dfs(int now,int val){
if(val>=ans) return;
if(now==p+1){
ans=val;
return ;
}
for(int i=1;i<=k;i++){
if(c[i]+a[now]<=m){
c[i]+=a[now];
dfs(now+1,val);
c[i]-=a[now];
}
}
k++;
c[k]+=a[now];
dfs(now+1,val+1);
c[k]-=a[now];
k--;
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>b[i];
}
cin>>s;
for(int i=1;i<=s;i++){
cin>>lst;
while(cin>>r){
G[lst].push_back(r);
G[r].push_back(lst);
lst=r;
if(cin.get()=='\n') break;
}
}
for(int i=1;i<=n;i++) if(!vis[i]) p++,build(i);
sort(a+1,a+1+p,cmp);
dfs(1,0);
cout<<ans;
return 0;
}

后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
更多推荐



所有评论(0)