CSP-J模拟3刘彦孜补题

日期:2024.10.3
学号:S06465
一:
总分数:
T1【IP地址(ip)】:100
T2【是否同构(same)】:100
T3【箱子(box)】:10
T4【社恐的聚会(party)】:30
二、比赛过程
第一题很水,用map映射就能过
第二题主要考察思维,多看看样例,思考思考
第三题用的合并果子的思路,但是没考虑全
第四题没多少思路,直接写了一个暴搜
三、比赛分析
T1【IP地址(ip)】:
1.题目大意
有n台设备,每个设备都有它的名称和IPv4地址,有q次询问,每次询问输出该IPv4地址对应的设备名称
2.比赛中的思考
直接用map映射
3.解题思路
直接用map映射
4.AC代码

#include<bits/stdc++.h>
using namespace std;
map<string,string> mp;
int n,q;
string s1,s2;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		cin>>s1>>s2;
		mp[s2]=s1;
	}
	scanf("%d",&q);
	for(int i=1;i<=q;i++){
		cin>>s1;
		cout<<mp[s1]<<"\n";
	}
	return 0;
}

T2【是否同构(same)】:
1.题目大意
一个有q组数据,每组有两个长度为n的数组a,b,如果交换数组a的前k项和k项交换位置,能变成数组b,就输出Yes,否则输出No
2.比赛中的思考
我是先找出a数组前半部分和b数组不相等的最后一个位置,然后交换这两部分,最后判断交换后是否相等
3.解题思路
先找出k可以在那个位置,然后交换这两部分,最后判断交换后是否相等
4.AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int t;
int n;
int a[N];
int b[N];
int k;
int f;
int main(){
	scanf("%d",&t);
	while(t--){
		k=0;
		f=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
		}
		for(int i=1;i<=n;i++){
			scanf("%d",&b[i]);
		}
		for(int i=1;i<=n/2;i++){
			if(a[i]!=b[i]){
				k=i;
			}
		}
		if(k==0){
			printf("Yes\n");
			continue;
		}
		for(int i=1;i<=k;i++){
			swap(a[i],a[n-k+i]);
		}
		for(int i=1;i<=n;i++){
			if(a[i]!=b[i]){
				f=1;
				break;
			}
		}
		if(f==0){
			printf("Yes\n");
		}
		else{
			printf("No\n");
		}
	}
	return 0;
}

T3【箱子(box)】:
1.题目大意
有n给箱子,每个箱子都有重量w[i],每我们可以将至多m个箱子合成一个重量为这几个箱子重量和的箱子,花费的体力是几个箱子的重量和。问将这些箱子合并成一个箱子需要花费的最少体力是多少
2.比赛中的思考
这个题和合并果子很像,我直接把合并果子写上了,没有考虑其他问题
3.解题思路
合并的时候可能会有当前情况不小于m的情况,所以要提前补0,然后再写合并果子的部分
4.AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;
long long a[N];
long long ans;
priority_queue<long long,vector<long long>,greater<long long> > q;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		q.push(a[i]);
	}
	if((n-1)%(m-1)>0){
		int cnt=m-1-(n-1)%(m-1);
		while(cnt--){
			q.push(0);
		}
	}
	while(q.size()>1){
		long long sum=0;
		for(int i=1;i<=m;i++){
			long long x=q.top();
			q.pop();
			sum+=x;
		}
		ans+=sum;
		q.push(sum);
	}
	printf("%lld",ans);
	return 0;
}

T4【社恐的聚会(party)】:
1.题目大意
有n个人想参与一个聚会,但是这个聚会只有两张桌子,这些人不想跟自己不认识的人坐在一起,问能不能将n 个人分在两张桌子,使得每张桌子的任意两个人都是相互认识的,如果能,输Yes,然后再输出两张桌子中人数最多的那张入座人数最少是多少,否则输出No
2.比赛中的思考
没有正经的思路,写了一个暴搜
3.解题思路
先用dfs判断能不能坐下n个人,然后再用分组背包的思路,求出这个桌子能否做下i个人,最后再输出
4.AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=550;
int n,m;
int cnt;
int a[N][N];
int sz[N][2];
int col[N];
bool f[N];
bool vis[N];
bool dfs(int u,int c){
	vis[u]=1;
	col[u]=c;
	sz[cnt][c]++;
	for(int i=1;i<=n;i++){
		if(i!=u&&(!a[i][u]||!a[u][i])){
			if(vis[i]){
				if(col[u]==col[i]){
					return 0;
				}
			}
			else if(!dfs(i,1-c)){
				return 0;
			}
		}
	}
	return 1;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			scanf("%d",&a[i][j]);
		}
	}
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			cnt++;
			if(!dfs(i,0)){
				printf("No\n");
				return 0;
			}
		}
	}
	m=n>>1;
	f[0]=1;
	for(int i=1;i<=cnt;i++){
		for(int j=m;;j--){
			if(j<sz[i][0]&&j<sz[i][1]){
				break;
			}
			if(j>=sz[i][0]){
				f[j]|=f[j-sz[i][0]];
			}
			if(j>=sz[i][1]){
				f[j]|=f[j-sz[i][1]];
			}
		}
	}
	for(int j=m;j>=1;j--){
		if(f[j]){
			printf("Yes\n%d",n-j);
			break;
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值