cf1786D. Letter Exchange(贪心)

传送门

具体思路就是贪心去凑, 对于iin, 需要出一个i, 要一个w, 即(i, w), 若有要一个i, 出一个w就能形成互补, 即(i, w) (w, i) 互补, 如果没有互补这种情况, 则要中转一次, 即 (i, w) (w, n) (n, i) 这种, 而对于iii, 就是需要转两次, (i, w)一次, (i, n)一次, 转完一次后都和第一种情况符合, 据题意牌面固定, 只可能出现这两种情况, 模拟即可。

#include <bits/stdc++.h>

using namespace std;

#define endl "\n"
#define debug cout<<"debug"<<endl
typedef long long ll;
typedef long double ld;
typedef pair<int, int> PII;
const double eps = 1e-8;
const double PI = 3.14159265358979323;
const int N = 2e5+10, M = 2*N, mod = 1e9+7;
const int INF = 0x3f3f3f3f;

int n;
string win = "win";

void solve()
{
    cin>>n;
    vector<vector<set<int>>> v(3, vector<set<int>> (3));
    for(int i = 1; i<=n; i++)
    {
        string s; cin>>s;
        for(int j = 0; j<3; j++)
        {
            for(int k = 0; k<3; k++)
            {
                if(j == k) continue;
                // inn 出一种, 出n要w // iii 出两种, 可以先出一种转成前者, 出i要n, 出i要w, 要中转
                int s1 = count(s.begin(), s.end(), win[j]);
                int s2 = count(s.begin(), s.end(), win[k]);
                if(s1>=2 && s2==0) v[j][k].insert(i); // 出win[j]要win[k]
            }
        }
    }
    vector<vector<int>> res;
    for(int i = 1; i<=n; i++)
    {
        for(int j = 0; j<3; j++)
        {
            for(int k = 0; k<3; k++)
            {
                // 出j要k 与 出k要j互补
                if(v[j][k].count(i)) // 有互补情况, 直接凑成
                {
                    if(v[k][j].size()>0)
                    {
                        auto it = v[k][j].begin();
                        res.push_back({i, j, *it, k});
                        v[j][k].erase(i), v[k][j].erase(it);
                    }else{ // 无互补情况 要转两次, 先转一次
                        for(int t = 0; t<3; t++)
                        {
                            if(v[k][t].size()>0)
                            {
                                auto it = v[k][t].begin();
                                res.push_back({i, j, *it, k}), v[j][t].insert(*it); // 转一次
                                v[j][k].erase(i), v[k][t].erase(it);
                                break; // 只转一次
                            }
                        }
                    }
                }
            }
        }
    }
    cout<<res.size()<<endl;
    for(auto t : res) cout<<t[0]<<" "<<win[t[1]]<<" "<<t[2]<<" "<<win[t[3]]<<endl;
}

int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    T = 1;
    cin>>T;
    while(T -- )
    {
        solve();
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值