P8296 [COCI2012-2013#2] KRIZALJKA 题解
upd 2022.7.8:修改了对
map 做法的解释以及删去了一个错误的小方法。
简单看了下题解区,两位搜索的和一位循环枚举的。我个人倾向于循环的方式。
题意
在六个字符串中选三个组成矩阵,矩阵中的横竖六个字符串刚好是这六个原串的字典序最小的方案。
分析
输入保证按字典序给出。
这句话说明了我们在枚举答案时不需要统一储存取最小的,只要输出第一个答案即可。
接下来谈一些细节方面的实现方式。
当枚举出三个字符串时比较容易得到纵向的三个字符串。
然而目前的题解似乎想复杂了,其实不需要一一判断其唯一性。
方法是把所有的六个字符串(包括枚举的和求出的)排序后连接起来,然后将原来的序列也这样操作,比较两者是否一致就可以了。
代码
基于以上思路,代码见下。
#include <bits/stdc++.h>
using namespace std;
string s[10],T,check;
bool flag=1;
int main()
{
for(int i=1;i<=6;i++) cin>>s[i],check=check+s[i];
for(int i=1;i<=6;i++)for(int j=1;j<=6;j++)for(int k=1;k<=6;k++)
if(i!=j&&j!=k&&i!=k)
{
string px[10];
for(int l=0;l<=2;l++)
px[l+1]=T+s[i][l]+s[j][l]+s[k][l];
px[4]=s[i],px[5]=s[j],px[6]=s[k];
sort(px+1,px+7);
string fl="";
for(int l=1;l<=6;l++) fl=fl+px[l];
if(fl==check)
{
cout<<s[i]<<endl<<s[j]<<endl<<s[k]<<endl;flag=0;
return 0;
}
}
if(flag) cout<<0;
}
注意到一段代码。
for(int l=0;l<=2;l++)
px[l+1]=T+s[i][l]+s[j][l]+s[k][l];
这段代码中的 T 是什么?
其实在这一点上我借鉴了 @xt__ 的代码。如果去掉这个或者改成空字符串都会有 bug。例如去掉就会变成空值,加上空字符串会是乱码。
之前我说这题不能用 map 来解决,但其实遇到样例 1 这样的相同情况我们比较的就不是其存在性,而是直接比较其出现的次数和原来的是否一致即可。
同时弥补之前的学术谬误,此处再给出代码。
#include <bits/stdc++.h>
using namespace std;
string s[10],T;
map<string,int> ans;
int main()
{
for(int i=1;i<=6;i++) cin>>s[i],ans[s[i]]++;
for(int i=1;i<=6;i++)for(int j=1;j<=6;j++)for(int k=1;k<=6;k++)
if(i!=j&&j!=k&&i!=k)
{
map<string,int> mp;
int flag2=1;
string px[10];
for(int l=0;l<=2;l++) px[l+1]=T+s[i][l]+s[j][l]+s[k][l];
px[4]=s[i],px[5]=s[j],px[6]=s[k];
for(int i=1;i<=6;i++) mp[px[i]]++;
for(int i=1;i<=6;i++) if(!mp[s[i]]||mp[s[i]]!=ans[s[i]]) flag2=0;
if(flag2)
{
cout<<s[i]<<endl<<s[j]<<endl<<s[k]<<endl;
return 0;
}
}
cout<<0;
}