[ABC326D] ABC Puzzle

思路

不难。

发现只有三个字母时果断状压,通过观察我们可以发现 \(n\)\(m\) 都很小,然后我们就可以想到暴搜了,我们可以对于每一行一行的去填数,这里我们发现只需要是的满足题目给出的那两个串的条件即可。

这里我们定义 \(hang_i,lie_i\) 表示第 \(i\) 行和第 \(i\) 列的状态(二进制下第 \(i\) 位为一表示第 \(i\) 个大写字母已经选过了),然后我们就可以发现如果第 \(i\) 行已经到了最后一个我们就可以去判断一下这一行填的第 \(1\) 个数是否与要求填的第一个数相同,若相同则继续往后填,如果这一列还没有填数则将要填的数和想要填的数进行比较即可。

细节见代码。

代码

#include <bits/stdc++.h>
using namespace std ;
#define int long long
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define rep1(i,x,y) for(int i=x;i>=y;i--)
#define fire signed
#define kong putchar(' ')
#define end putchar('\n')
#define in(x) scanf("%lld",&x)
#define lcm(x,y) x*y/__gcd(x,y)
#define il inline
il void print(int x) {
	if(x>=10) print(x/10);
	putchar(x%10+'0');
}
int n;
string s,t;
char c[10][10];
int lie[10],hang[10];
char nowx[10],nowy[10]; 
bool check(int x,int y,int i,int j,char c) { //判断是否匹配
	if(x==0) if(c!=t[j]) return false;
	if(y==0) if(c!=s[i]) return false;
	return 1;
}
void dfs(int x,int y) {
	if(x==n+1&&y==1) {
		int f=0;
		rep(i,1,n) if(lie[i]!=7||hang[i]!=7) return ; //判断每一行和每一列上是否都用到了三个字母
		puts("Yes");
		rep(i,1,n) {
			rep(j,1,n) {
				cout<<c[i][j];
			}
			cout<<endl;
		}
		exit(0);
	}
	rep(i,0,2) {
		if((lie[y]&(1<<i))!=(1<<i)&&(hang[x]&(1<<i))!=(1<<i)&&check(lie[y],hang[x],x,y,i+'A')) {//判断是否冲突
			int ip=1<<i;
			lie[y]|=(1<<i);
			hang[x]|=ip;
			c[x][y]=(i+'A');
			if((y+1)>n&&hang[x]==7) dfs(x+1,1); //跳到下一行第一个
			else if(y+1<=n)dfs(x,y+1); //这一行的下一个
			lie[y]^=ip;
			hang[x]^=ip;
		}
	}
	c[x][y]='.';
	if((y+1)>n&&hang[x]==7) dfs(x+1,1);
	else if(y+1<=n)dfs(x,y+1);
}
fire main() {
	cin>>n>>s>>t;
	s=" "+s;
	t=" "+t;
	dfs(1,1);
	puts("No");
	return false;
}

posted @ 2024-01-31 11:40  highkj  阅读(11)  评论(0)    收藏  举报