N皇后问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 22760 Accepted Submission(s): 10136
Problem Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
#include<bits/stdc++.h>
using namespace std;
int n, tot=0;
int col[12]={0};
bool check(int c,int r){
for(int i = 0; i < r; i++)
if(col[i] == c || (abs(col[i]-c) == abs(i-r))) return false;
return true;
}
void DFS(int r){
if(r==n){
tot++;
return;
}
for(int c = 0;c<n;c++){
if(check(c,r)){
col[r]=c;
DFS(r+1);
}
}
}
int main(){
int ans[12] = {0};
for(n =0;n <= 10;n++){
memset(col, 0,sizeof(col));
tot=0;
DFS(0);
ans[n] = tot;
}
while(cin>>n){
if(n==0) return 0;
cout<<ans[n]<<endl;
}
return 0;
}
P1443 马的遍历
#include<bits/stdc++.h>
using namespace std;
int n, m, fx, fy;
int a[400 + 5][400 + 5];
int dir[8][2] = { {-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2} };
struct node {
int x, y;
};
void bfs(int dx, int dy) {
queue<node> q;
node start, next;
start.x = dx;
start.y = dy;
q.push(start);
while (!q.empty()) {
start = q.front();
q.pop();
for (int i = 0; i < 8; i++) {
next.x = start.x + dir[i][0];
next.y = start.y + dir[i][1];
if (next.x <= 0 || next.x > n || next.y <= 0 || next.y > m || a[next.x][next.y] != 0 || (next.x == dx && next.y == dy)) continue;
a[next.x][next.y]=a[start.x][start.y]+1;
q.push(next);
}
}
}
int main() {
cin >> n >> m >> fx >> fy;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) a[i][j] = 0;
}
bfs(fx, fy);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (a[i][j] != 0 || (i == fx && j == fy)) printf("%-5d", a[i][j]);
else printf("%-5d", -1);
}
cout << endl;
}
return 0;
}
P1135 奇怪的电梯
#include<bits/stdc++.h>
using namespace std;
int n, a, b;
int k[200+5],vis[200+5];
void bfs(int da, int db) {
queue<int> q;
vis[da] = 0;
int start,next;
start=da;
q.push(start);
while (!q.empty()) {
start = q.front();
q.pop();
for (int i = -1; i <=1; i+=2) {
next = start + i*k[start];
if (next <= 0 || next > n || vis[next] != -1) continue;
vis[next] = vis[start]+1;
if(next==db)break;
q.push(next);
}
}
}
int main() {
cin >> n >> a >> b;
for (int i = 1; i <= n; i++) {
cin>>k[i];
vis[i]=-1;
}
bfs(a, b);
cout<<vis[b]<<endl;
return 0;
}
P2895 [USACO08FEB]Meteor Shower S
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;//无限大
int mp[302][302];//表示流星到达时间
bool v[302][302];//有无走过
struct point {
int x,y,step;//步数也就是时间
};
int dx[]= {0,0,-1,1},dy[]= {-1,1,0,0};//四个方向
int BFS(point a) {
queue<point>q;
q.push(a);
v[a.x][a.y]=1;//标记为走过
while(!q.empty()) {
point b=q.front();
q.pop();
for(int d=0; d<4; ++d) {
point c;
c.x=b.x+dx[d],c.y=b.y+dy[d],c.step=b.step+1;
if(c.x==-1||c.y==-1)continue;//判边界
if(mp[c.x][c.y]==inf)return c.step;//永远不会有流星
if(c.step<mp[c.x][c.y]&&!v[c.x][c.y]) {//在流星到达之前并且没走过
q.push(c);
v[c.x][c.y]=1;//标记为走过
}
}
}
return -1;
}
int main() {
int m;
scanf("%d",&m);
memset(mp,0x3f,sizeof(mp));//由于是按字节赋值,刚好是mp[?][?]=inf
for(int i=1,x,y,t; i<=m; ++i) {
scanf("%d%d%d",&x,&y,&t);
mp[x][y]=min(mp[x][y],t);
for(int d=0; d<4; ++d) {
if(x+dx[d]==-1||y+dy[d]==-1)continue;//判边界
mp[x+dx[d]][y+dy[d]]=min(mp[x+dx[d]][y+dy[d]],t);
//更新此位置流星最早到达时间
}
}
printf("%d",BFS((point) {
0,0,0
}));
//相当于
//point a;
//a.x=a.y=a.step=0;
//printf("%d",BFS(a));
return 0;
}
P1605 迷宫
#include<iostream>//个人建议不使用万能头文件,如果要使用万能头文件,就不能定义数组map;
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
int map[6][6];//地图;
bool temp[6][6];//走过的标记;
int dx[4]={0,0,1,-1};//打表;
int dy[4]={-1,1,0,0};//打表;
int total,fx,fy,sx,sy,T,n,m,l,r;//total计数器,fx,fy是终点坐标,sx,sy是起点坐标,T是障碍总数,n,m是地图的长和宽,l,r是障碍的横坐标和纵坐标;
void walk(int x,int y)//定义walk;
{
if(x==fx&&y==fy)//fx表示结束x坐标,fy表示结束y坐标;
{
total++;//总数增加;
return;//返回,继续搜索;
}
else
{
for(int i=0;i<=3;i++)//0——3是左,右,下,上四个方向;
{
if(temp[x+dx[i]][y+dy[i]]==0&&map[x+dx[i]][y+dy[i]]==1)//判断没有走过和没有障碍;
{
temp[x][y]=1;//走过的地方打上标记;
walk(x+dx[i],y+dy[i]);
temp[x][y]=0;//还原状态;
}
}
}
}
int main()
{
cin>>n>>m>>T;//n,m长度宽度,T障碍个数
for(int ix=1;ix<=n;ix++)
for(int iy=1;iy<=m;iy++)
map[ix][iy]=1;//把地图刷成1;
cin>>sx>>sy;//起始x,y
cin>>fx>>fy;//结束x,y
for(int u=1;u<=T;u++)
{
cin>>l>>r;//l,r是障碍坐标;
map[l][r]=0;
}
walk(sx,sy);
cout<<total;//输出总数;
return 0;
}
一个基本的深搜模板
int search(int t)
{
if(满足输出条件)
{
输出解;
}
else
{
for(int i=1;i<=尝试方法数;i++)
if(满足进一步搜索条件)
{
为进一步搜索所需要的状态打上标记;
search(t+1);
恢复到打标记前的状态;//也就是说的{回溯一步}
}
}
}