我的思路是,按行顺序来放到列上,所以行不会重复,同时放到列上时,判断该列有没有占用,所以列不会重复,那么这个题,关键点就是处理对角线,可以发现,选择了一个点(x,y),那么他的两条对角线上的点都不能选了,发现这两条对角线上的点(x1,y1)分别满足x1+y1=x+y 和 x1-y1=x-y
那么在判断交叉线是用两个数组,一个记录x+y值占用过没,另一个记录x-y+n占用过没(因为可能有负数)
ps:本来我是用map来记录x+y值和x-y值的,不行!因为会有二者恰好相同,并且会超时(QwQ)
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
const int N=20,mod=1e9+7;
const int INF=0x3f3f3f3f;
int ans[N];//ans[i]:=第i行放置到了第ans[i]列
int vis[N];
int n,cnt=0;
int cha[N*2],he[N*2];
void dfs(int line){//第line行在第x列
if(line==n+1){
cnt++;
if(cnt<=3){
for(int i=1;i<n;i++){
printf("%d ",ans[i]);
}
printf("%d\n",ans[n]);
}
return ;
}
if(line>n+1){
return ;
}
for(int i=1;i<=n;i++){//第i列
int x=line+i,y=i-line+n;
if(!vis[i]&&!he[x]&&!cha[y]){
//printf("%d %d\n",line,i);
he[x]=1;
cha[y]=1;
vis[i]=1;
ans[line]=i;
dfs(line+1);
vis[i]=0;
he[x]=0;
cha[y]=0;
}
}
}
int main(){
scanf("%d",&n);
dfs(1);
printf("%d\n",cnt);
}
我傻了,直接上了dfs,然后错错错,其实这个题明显要判断方向啊,朝着一个方向搜索下去!
而且本来是想暴力写的,但是dfs更简洁,把每一步存下来,搜到结果的时候再处理!
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
const int N=105,mod=1e9+7;
const int INF=0x3f3f3f3f;
char t[8]={'y','i','z','h','o','n','g'};
char a[N][N];
int n,vis[N][N];
struct A{
int x,y;
}path[10];
int dx[8]={-1,-1,-1,0,1,1,1,0},dy[8]={-1,0,1,1,1,0,-1,-1};
void dfs(int x,int y,int dep,int fa){
if(dep==7){
for(int i=0;i<7;i++){
vis[path[i].x][path[i].y]=1;
}
return ;
}
if(dep>7)return ;
int nx=x+dx[fa],ny=y+dy[fa];
if(nx>=0&&nx<n&&ny>=0&&ny<n&&a[nx][ny]==t[dep]){
path[dep].x=nx;
path[dep].y=ny;
dfs(nx,ny,dep+1,fa);
}
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%s",a[i]);
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(a[i][j]=='y'){
path[0].x=i;path[0].y=j;
for(int k=0;k<8;k++){
int nx=i+dx[k],ny=j+dy[k];
if(nx>=0&&nx<n&&ny>=0&&ny<n&&a[nx][ny]=='i'){
path[1].x=nx;path[1].y=ny;
dfs(nx,ny,2,k);
}
}
}
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(vis[i][j])printf("%c",a[i][j]);
else printf("*");
}
printf("\n");
}
}
这个思路很巧妙,就是从不在圈内的0开始搜索,遇到1就停止了,那么1和1内部都搜不到,标记为2
但是我们怎么找不在圈内的0呢?
图存到a[1-n][1-n]里,我们把n*n的图向外扩一圈,从(0,0)开始搜就行了,总能找到“突破口”,除非图是被1全包围的
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
const int N=35,mod=1e9+7;
const int INF=0x3f3f3f3f;
int n;
int a[N][N],vis[N][N];
typedef pair<int,int>P;
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
void dfs(int x,int y){
vis[x][y]=1;
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];
if(nx>=0&&nx<=n+1&&ny>=0&&ny<=n+1&&!vis[nx][ny]&&a[nx][ny]!=1){
dfs(nx,ny);
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
}
}
dfs(0,0);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(vis[i][j])printf("0");
else if(a[i][j]==1)printf("1");
else printf("2");
printf("%c",j==n?'\n':' ');
}
}
}