Codeforces Round #850 (Div. 1, based on VK Cup 2022 - Final Round) B.Letter Exchange(思维题 置换三元环 补写法)

题目

m(m<=1e5)个人,每个人有一个长度为3的仅由w、i、n组成的串,

且m个人恰有m个w,m个i,m个n,

现在需要交换,每次可以选择两个人a、b,将a的某一个字母和b的某一个字母交换

若干次交换后,使得每个人手中的串恰好是win

输出最小的交换次数,以及对应的交换序列

实际t(t<=1e4)组数据,保证m总和不超过1e5

思路来源

cuiaoxiang代码

题解

赛中搞了150行,用了1个小时,实际60-70行,20分钟就差不多了

首先,把win字母对应标记成012,则只有10种情况,其中012是不用换的

000,111,222

001,110

002,220

112,221

012

而,0多1少,对应000和002两种情况,记到vector<int>a[0][1]内,表示0需要给1一个

其他对应情况,依次类推

其中,000,既出现在0多1少的情况中,也出现在0多2少的情况中

1. 二元环,a[0][1]<->a[1][0],a[0][2]<->a[2][0],a[1][2]<->a[2][1],优先操作

2. 不能操作后,则只剩三元环,a[0][1]->a[1][2]->a[2][0],a[1][0]->a[0][2]->a[2][1],操作即可

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<array>
using namespace std;
const string S="win";
int T,n;
vector<int>a[3][3];
int g(char c){return S.find(c);}
bool has(vector<int>&x){return !x.empty();}
int get(vector<int>&x){int y=x.back();x.pop_back();return y;}
string s;
int main(){
    cin>>T;
    while(T--){
        cin>>n;
        for(int i=0;i<3;++i){
            for(int j=0;j<3;++j){
                a[i][j].clear();
            }
        }
        for(int i=1;i<=n;++i){
            cin>>s;
            vector<int>cnt(3);
            for(int j=0;j<3;++j){
                cnt[g(s[j])]++;
            }
            for(int x=0;x<3;++x){
                for(int y=0;y<3;++y){
                    if(x==y)continue;
                    if(cnt[x]>1 && cnt[y]<1){
                        a[x][y].push_back(i);
                        cnt[x]--;
                        cnt[y]++;
                    }
                }
            }
        }
        vector<array<int,4>>ans;
        for(int x=0;x<3;++x){
            for(int y=x+1;y<3;++y){
                vector<int>&fi=a[x][y];
                vector<int>&se=a[y][x];
                while(has(fi) && has(se)){
                    int f=get(fi),s=get(se);
                    ans.push_back({f,x,s,y});
                }
            }
        }
        {
            vector<int>&fi=a[1][0];
            vector<int>&se=a[0][2];
            vector<int>&th=a[2][1];
            while(has(fi) && has(se) && has(th)){
                int f=get(fi),s=get(se),t=get(th);
                ans.push_back({f,1,s,0});
                ans.push_back({s,1,t,2});
            }
        }
        {
            vector<int>&fi=a[0][1];
            vector<int>&se=a[1][2];
            vector<int>&th=a[2][0];
            while(has(fi) && has(se) && has(th)){
                int f=get(fi),s=get(se),t=get(th);
                ans.push_back({f,0,s,1});
                ans.push_back({s,0,t,2});
            }
        }
        cout<<(int)ans.size()<<endl;
        for(auto [i,x,j,y]:ans){
            cout<<i<<" "<<S[x]<<" "<<j<<" "<<S[y]<<'\n';
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Code92007/article/details/128895633