中级光能
题目描述 Description
展台被分成N*N个格子,某些格子中有钻石,为了防盗,需要建立防盗**,防盗**是一种光电检测装置,它可以检测它所在的行和列以及两个对角线共四条线上是否有人触碰。当然已经放置了钻石的位置是不能安装这个装置的,同时四条线上不能有多个装置,因为他们会互相干扰,发出错误的信号。针对以上防盗装置,我们想知道有多少种布局方案。
输入描述 Input Description
第一行一个整数N,表示展台的大小 接下来N行,每行N个0或1的整数,如果一个整数为0,表示对应的位置可以放防盗装置,如果一个整数为1,表示对应的位置放置了展品。
输出描述 Output Description
一个整数,表示总共有多少种放法。
样例输入 Sample Input
4 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
样例输出 Sample Output
1
数据范围及提示 Data Size & Hint
0<N<=10
#include<iostream>
using namespace std;
int n,map[105][105],ans,a[100005],b[100005],c[10005];
bool check(int x){//若行内没有可以放的位置,直接递归
for(int i=1;i<=n;i++)
if(map[x][i]==0)return false;
return true;
}
void dfs(int x){//当前正在填第x行
if(x>n){
ans++;
return;
}
if(!check(x)){
for(int i=1;i<=n;i++){//枚举列
if(map[x][i]==0&&a[x-i+n]==false&&b[x+i]==false&&c[i]==false){
a[x-i+n]=true;
b[x+i]=true;
c[i]=true;
dfs(x+1);
a[x-i+n]=false;
b[x+i]=false;
c[i]=false;
}
}
}
else dfs(x+1);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
cin>>map[i][j];
}
dfs(1);
cout<<ans;
return 0;
}
中级启示者
check函数不需要,直接枚举,然后枚举完再继续搜
你这样会少一些方案,因为就算 !check(x) ,也可以不放
但是这样可能会出现一个都不放的情况,还要加个参数判断
核心
void dfs(int pos,int flag){
if(pos>n){
if(flag) ans++;
return ;
}
for(int i=1;i<=n;i++){
if(!vis[i]&&!a[pos-i+10]&&!b[pos+i]&&!m[pos][i]){
vis[i]=true;
a[pos-i+10]=true;
b[pos+i]=true;
dfs(pos+1,flag+1);
vis[i]=false;
a[pos-i+10]=false;
b[pos+i]=false;
}
}
dfs(pos+1,flag);
return ;
}