日期:2023.10.2
学号:s07661
一.比赛概况:
总分400分,拿到140分,其中第1题20分,2题70分,3题50分,4题0分,
二. 比赛过程
第一题模拟,做了个50分,第二题用sort,本身思路也知道超时,70不错了,第三题枚举20分错了,第四题就是不会做
三. 解题报告
一.人员借调
1.题目大意
B 地的领导想借调小可帮忙处理 件事情,小可处理第 件的耗时为分钟。如果小可在 B 地待连续大于等于240分钟时,A 地领导会非常的不高兴,将强制把小可留在 A 地 天( 分钟), 天结束后小可可以继续留在 A 地正常工作或者继续前往B 地帮忙处理事情。
于是,小可有了一个对策,在 分钟快到的时候就此 B 地回到 A 地,然后再去 B 地,这样的话
分钟就会重新计时。注意:从 A 地往返一次 B 地会耗时 分钟(这个时间不计算到待在 B 地的时间)。注:这个事情必须处理完才可以继续后面的内容
2.比赛中的思考
我一步一步模拟,一步一步递推,试了很多样例,问题都不大,想着一步一步加,然后判断是否超过240,加上下个数是否大于240,进行操作。
3.解题思路
用累加器判断什么时候要回去,把这些数都累加上,最后判断有无超过240的,如果有,输出结果加10480。
4 .AC代码
#include<bits/stdc++.h>
using namespace std;
long long n,a[1005],num[1000005];
int main(){
long long sum=0,sum1=10480,sum2=400,maxn=0,t=0;
cin>>n;
for(long long i=1;i<=n;i++){
cin>>a[i];//任务
sum1+=a[i];//累加
maxn=max(maxn,a[i]);//找最大值
}
for(long long i=1;i<=n;i++){
if(t+a[i]>=240){//什么时候回去
sum2+=400+a[i];
t=a[i];
}else{
t+=a[i];
sum2+=a[i];
}
}
if(maxn>=240){//有无超过240的
cout<<sum1<<"\n";
}
else{
cout<<min(sum1,sum2)<<"\n";
}
return 0;
}
二.计算
1.题目大意
计算需要使用到三个整数 m,n,k
计算条件如下(设 x 为满足计算条件的数字):1:m≤x≤n 2:x 在十进制下所有位上的数字之和为 k 根据计算条件得到的 x 可能会很多,请输出十进制下所有位上的数字的积最大的那个
2.比赛中的思考
暴力枚举,会超时
3.解题思路
打表,节省时间
4 .AC代码
#include<bits/stdc++.h>
using namespace std;
int t;
int m,n,k,cnt;
struct node{
int dc,c;
}a[5000005];
int main(){
for(int i=1;i<=5000005;i++){//循环打表
int t=i,sum=0,sum1=1;
while(t>0){
sum+=t%10;//数位和
sum1*=t%10;//数位积
t/=10;
}
a[i].dc=sum;//打表数组
a[i].c=sum1;
}
cin>>t;
for(int i=1;i<=t;i++){
int maxn=-1e9,id;
cin>>m>>n>>k;//输入
for(int j=m;j<=n;j++){
if(a[j].dc==k&&maxn<a[j].c){//判断求最大
maxn=a[j].c;
id=j;
}
}
cout<<id<<" "<<maxn<<"\n";//输出
}
return 0;
}
三.智能公交
1.题目大意
现在有 m 个人要依次乘坐智能公交,每个人都会等待智能公交停在 x 站台之后在按动当前站台按钮准备乘坐公交。现在已知第 i 个人都是从 a 站台到 b 站台。请你计算 x ,使得智能公交移动距离最短。最终输出 x 和最短的距离,x 若有多个,输出最小的一个。
2.比赛中的思考
暴力,没什么可说的,就是写的有些问题,本来也没想AC。
3.解题思路
因为要考虑x到两个点的距离和,
把输入的两个数组合并,就是D4货仓选址的题。
4 .AC代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
bool flag;
int main(){
long long a[1000005],b[1000005],c[2000005],cnt=0,minn=1e9,maxn=-1e9,sum=0;
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a[i]>>b[i];
c[++cnt]=a[i];//合并
c[++cnt]=b[i];
sum+=(b[i]-a[i]);
}
sort(c+1,c+m+m+1);//排序
int zhan=c[m];
for(int i=1;i<=2*m;i++){
sum+=abs(zhan-c[i]);//货舱选址操作
}
cout<<zhan<<" "<<sum;//输出公交停靠的位置和最短距离
return 0;
}
四.异或和
1.题目大意
多个集合中总共有 n 个数字,并且已知每个数字的大小 ai 和属于某个集合 bi。
在一个集合中选择一个数字,收益为这个数字的大小,选择多个数字,收益为这些数字的异或和。
总收益为每个集合的收益之和。注意:最多从中选择 m(m≤n) 个数字,使这些数字总收益最大。
2.比赛中的思考
收到这道题的时候,大脑直接宕机了,也没剩多长时间,随便蒙了个代码就交了
3.解题思路
先处理每组数据,再处理dp数组, 在构成j所需的个数 最后枚举n组,用分组背包解决这道题,输出dp2[m];
4 .代码
补题时,先做了两个十分的
#include<iostream>
#include<cstring>
#define INF 0x3f3f3f3f
#define ll long long
#define N 1000005
#define M 100005
using namespace std;
int dp[2005][2050]={0};
int main(){
int n,m,a[2005];
cin>>n>>m;
for(int i=1; i<=n; i++){
int x;
cin>>a[i]>>x;//输入
dp[1][a[i]] = 1;
}
for(int i=2; i<=n; i++){
for(int j=1; j<=2047; j++){
if(dp[i-1][j]){//如果前i-1个数能够构造j
dp[i][j] = 1;
dp[i][j^a[i]] = 1;//状态转移
}
}
}
for(int i=2047; i>=1; i--){
if(dp[n][i]){
cout<<i;//输出
break;
}
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n,m,maxn,dp[2505][2505]={0},a[2505];
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
int x;
cin>>a[i]>>x;//输入
dp[1][a[i]]=x;//判边界
}
for(int i=2;i<=n;i++){
for(int j=1;j<=2047;j++){
dp[i][j]=min(dp[i][j],dp[i-1][j]);//状态转移
dp[i][j^a[i]]=min(dp[i][j^a[i]],dp[i-1][j]+1);
}
}
int maxx=0;
for(int i=1;i<=10;i++){
if(dp[n][i]<=m){
maxx=max(i,maxx);//判最大
}
}
cout<<maxx;//输出最大值
return 0;
}
然后是AC代码
#include<bits/stdc++.h>
using namespace std;
int n,m,maxn,dp[2505][2505]={0},a[2505][2505],cnt[2505],num[2505][2047]={0};
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;//输入
cnt[y]++;
a[y][cnt[y]]=x;
}
for(int zu=1;zu<=2000;zu++){//处理每组
if(cnt[zu]==0)continue;
memset(dp,0x3f,sizeof dp);
for(int i=1;i<=cnt[zu];i++){
dp[i][a[zu][i]]=1;//前i个数构成a[zu][i]一定只需要一个数本身
}
//处理dp数组
int x=0x3f3f3f3f;
for(int i=2;i<=cnt[zu];i++){
for(int j=1;j<=2047;j++){
if(dp[i-1][j]!=x){
dp[i][j]=min(dp[i][j],dp[i-1][j]);
dp[i][j^a[zu][i]]=min(dp[i][j^a[zu][i]],dp[i-1][j]+1);//状态转移
}
}
}
for(int j=1;j<=2047;j++){
if(dp[cnt[zu]][j]!=x){
int k=dp[cnt[zu]][j];//构成j所需的个数
num[zu][k]=max(num[zu][k],j);
}
}
}
int dp2[2005]={0};
for(int i=1;i<=2000;i++){//枚举n组
for(int j=m;j>=1;j--){//背包容量
for(int k=1;k<=cnt[i];k++){//枚举放几个数据进去
if(j>=k){
dp2[j]=max(dp2[j],dp2[j-k]+num[i][k]);
}
}
}
}
cout<<dp2[m];
return 0;
}
总结:今天比昨天有进步,在题更难的情况下,分比昨天还高,也适应了现在的考试机制,明天继续加油,在进步一点点,争取省一!