题意:给你一些序列,要求把这些序列翻转之后能首尾相连(01,10),并且字符串不能相同,询问最小步数;
1.我们只关心这个字符串首尾位置,一共只有四种情况:00,01,10,11;00 和 11 是没必要翻转的,剩下 01,10 只要存在就可以相互抵消(0110,1001这种),剩下多的 01 or 10,就是我们最后需要翻转的字符串,数量为abs(num01-num10)/2;
2.为了满足字符串不能相同,一开始就记录下哪写字符串不可以翻转,例,假如s翻转之后为rev,rev出现过则说明s不可翻转,而同时rev也不可翻转,因为rev翻转之后为s,而s是一定不会变的
模一模大佬的代码QAQ
int n;
string s[MAXN];
int32_t main()
{
//fast;
int t;cin >> t;
while (t--)
{
cin >> n;
for (int i = 0; i < n; ++i) cin >> s[i];
set<string> seen, bad;
int zz = 0, oo = 0, zo = 0, oz = 0;
for (int i = 0; i < n; ++i)
{
string t = s[i];
if (t[0] == '0' && t[t.length() - 1] == '0') zz++;
else if (t[0] == '0')//01
{
zo++;
string rev(t.rbegin(), t.rend());//
if (seen.count(rev))//
bad.insert(t),bad.insert(rev);
seen.insert(t);
}
else if (t[t.length() - 1] == '0')//10
{
oz++;
string rev(t.rbegin(), t.rend());
if (seen.count(rev)) bad.insert(t),bad.insert(rev);
seen.insert(t);
}
else oo++;
}
if (zo == 0 && oz == 0)
{
if (zz == 0 || oo == 0) cout << 0 << '\n'<< '\n';
else cout << -1 << '\n';
}
else
{
int ans = abs(zo - oz) / 2;cout << ans << '\n';
for (int i = 0; i < n; ++i)
{
if (ans == 0) break;
if (zo > oz && s[i][0] == '0' && s[i].back() == '1' && !bad.count(s[i]))
ans--,cout << i + 1 << ' ';
if (oz > zo && s[i][0] == '1' && s[i].back() == '0' && !bad.count(s[i]))
ans--,cout << i + 1 << ' ';
}
cout << '\n';
}
}
return 0;
}
Codeforces Round #606 (Div. 2) D. Let's Play the Words?(贪心+map)
原文地址:https://www.cnblogs.com/Herlo/p/12063583.html
时间: 2024-10-29 15:45:19