codeforces 850 D (模拟)

题目
题意: 给定m个w、i、n,随机分配给m个人,每人3个字母。现在可以让任意两个人交换手中的一个字母,求最少需要交换多少次并输出方案.
思路: 如果某个人多w且没有i,就标记为w->i;如果某个人多i且没有w,就标记i->w,二者可以交换满足对方的条件。依次类推。
但是还要注意另一种情况,如果存在 w->i, i->n, n->w; w->n, n->i, i->w. 不能相互抵消,但是可以通过两次交换满足这三个要求。1和2先换,2和3的需求就变成互补的了,2和3再换.
代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n,m,k,T;
int get(int a,int b) //哪种交换 
{
	if(a==1&&b==2) return 1;
	if(a==2&&b==1) return 2;
	if(a==1&&b==3) return 3;
	if(a==3&&b==1) return 4;
	if(a==2&&b==3) return 5;
	if(a==3&&b==2) return 6;
}
void output(int x)
{
	if(x==1) cout<<'w';
	if(x==2) cout<<'i';
	if(x==3) cout<<'n';
	cout<<' ';
}
int cnt[N][4];
vector<int> va[7];
struct node{
	int l;
	int t1;
	int r;
	int t2;
	void print()
	{
		cout<<l<<" ";
		output(t1);
		cout<<r<<" ";
		output(t2);
		cout<<"\n";
	}
};
void solve()
{
	vector<node> res;
	m = 3;
	cin>>n;
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j) cnt[i][j] = 0;
		char ch;
		for(int j=0;j<m;++j)
		{
			cin>>ch;
			if(ch=='w') cnt[i][1]++;
			if(ch=='i') cnt[i][2]++;
			if(ch=='n') cnt[i][3]++;
		}
		int idx1 = 0; //哪个字母多
		int idx2 = 0,idx3 = 0; //哪些字母少
		for(int j=1;j<=m;++j)
		{
			if(cnt[i][j]>1) idx1 = j;
			if(cnt[i][j]==0)
			{
				if(!idx2) idx2 = j;
				else idx3 = j;
			}
		}
		if(idx1&&idx2) va[get(idx1,idx2)].push_back(i);
		if(idx1&&idx3) va[get(idx1,idx3)].push_back(i); 
	}
	for(int i=1;i<=5;i+=2)
	{
		while(va[i].size()&&va[i+1].size())
		{
			int idx1 = va[i].back();
			int idx2 = va[i+1].back();
			va[i].pop_back(); va[i+1].pop_back();
			if(i==1)
			res.push_back({idx1,1,idx2,2});
			if(i==3)
			res.push_back({idx1,1,idx2,3});
			if(i==5)
			res.push_back({idx1,2,idx2,3});
		}
	}
	int l = 1,mid = 5,r = 4;
	while(va[l].size()&&va[mid].size()&&va[r].size())
	{
		int idx1 = va[l].back();
		int idx2 = va[mid].back();
		int idx3 = va[r].back();
		va[l].pop_back(); va[mid].pop_back(); va[r].pop_back();
		res.push_back({idx1,1,idx2,2});
		res.push_back({idx2,1,idx3,3});
	}
	l = 3,mid = 6,r = 2;
	while(va[l].size()&&va[mid].size()&&va[r].size())
	{
		int idx1 = va[l].back();
		int idx2 = va[mid].back();
		int idx3 = va[r].back();
		va[l].pop_back(); va[mid].pop_back(); va[r].pop_back();
		res.push_back({idx1,1,idx2,3});
		res.push_back({idx2,1,idx3,2});
	}
	cout<<res.size()<<"\n";
	for(auto &item:res)
	{
		item.print();
	}
}
signed main(void)
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>T;
	while(T--) solve();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值