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;
}
posted @ 2022-02-18 11:04  l_x_y  阅读(42)  评论(0编辑  收藏  举报