CF47C Crossword 题解
题意
有 \(6\) 个字符串,让你把他们摆成一个8字形,使得交叉处相等,并且使得最后组合成的图形字典序最小。
分析
因为字符串的个数很小,所以可以枚举这 \(6\) 个字符串的每一个排列。观察样例可以发现,一种排列是合法的当且仅当 \(7\) 个交叉处的字符相同 \((\) 详见代码 \()\) 。如果当前枚举到的排列合法,且它的字典序比之前的答案小,就把答案更新成这个排列的结果,最后输出结果即可。
代码
#include <bits/stdc++.h>
#define elif else if
using namespace std;
const int MAXN=37;
vector<string>s;
vector<string>tmp,ans;
bool check(int l1,int l2,int l3,int l4,int l5,int l6)
{
return l1+l3-1==l2
&&l4+l6-1==l5
&&s[1][0]==s[4][0] //左上角的交叉处
&&s[4][l4-1]==s[2][0] //最左列,第二个交叉处
&&s[5][l5-1]==s[3][0] //中间一列最后一个交叉处
&&s[5][0]==s[1][l1-1] //第一行,第二个交叉处
&&s[2][l1-1]==s[5][l4-1] //中心的交叉处
&&s[6][0]==s[2][l2-1] //最右列,第一个交叉处
&&s[6][l6-1]==s[3][l3-1]; //右下角的交叉处
}
int main()
{
int i,j;bool flag=false;
s.resize(7);
for(i=1;i<=6;i++) cin>>s[i];
sort(s.begin()+1,s.begin()+7);
do
{
//从上至下将横行编成1-3号,从左至右将竖列编成4-6号
int l1=s[1].size(),l2=s[2].size(),l3=s[3].size(),l4=s[4].size(),l5=s[5].size(),l6=s[6].size();
if(check(l1,l2,l3,l4,l5,l6))
{
tmp=vector<string>(l5,string(l2,'.')); //将整个结果初始化
for(i=0;i<l5;i++)
{
if(!i) for(j=0;j<l1;j++) tmp[i][j]=s[1][j]; //给第一行赋值
if(i==l4-1) for(j=0;j<l2;j++) tmp[i][j]=s[2][j]; //给中间一行赋值
if(i==l5-1) for(j=l1-1;j<l2;j++) tmp[i][j]=s[3][j-l1+1]; //给最后一行赋值
tmp[i][l1-1]=s[5][i]; //给中间一列赋值
if(i<l4) tmp[i][0]=s[4][i]; //给第一列赋值
if(i>=l4) tmp[i][l2-1]=s[6][i-l4+1]; //给最后一列赋值
}
if(!flag) ans=tmp,flag=true;
elif(ans>tmp) ans=tmp; //更新答案
}
}while(next_permutation(s.begin()+1,s.begin()+7));
if(!flag) printf("Impossible\n"); //没有可行解
else
{
for(i=0;i<ans.size();i++)
{
for(j=0;j<ans[i].size();j++) printf("%c",ans[i][j]);
putchar(10);
}
}
return 0;
}