您的位置:首页 > 其它

dfs模板(回溯、四皇后)poj1321

2011-04-25 00:08 225 查看
#include<cstdio>
#include<cstdlib>
#include<cstring>
//using namespace std;
char mat[12][12];
int vis[12];
int cnt,n;
void dfs(int r,int k)
{
int i;
if(k == 0) {cnt ++;return;}
if(r >= n) return ;
for(i = 0; i < n; i ++)
{
if(!vis[i] && mat[r][i] == '#')
{
vis[i] = 1;
dfs(r+1,k-1);
vis[i] = 0;
}
}
//有一点要注意:如果摆放的柜子数目没行列数多,那么就要进行下面这一步了
dfs(r+1,k);
}
int main()
{
int k,i,j;
while(scanf("%d%d",&n,&k)==2)
{
if(n==-1 && k==-1) break;
cnt = 0;
memset(vis,0,sizeof(vis));
for(i=0; i < n; i++)
{
getchar();
for(j=0; j < n; j ++)
scanf("%c",&mat[i][j]); //这个地方曾经因为写成%s而wa了好几次
}
dfs(0,k);
printf("%d/n",cnt);
}
return 0;
}


题目:

棋盘问题

Time Limit: 1000MSMemory Limit: 10000K
Total Submissions: 10976Accepted: 5370
Description
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
Output
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
Sample Input
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1

Sample Output
2
1


再举一例:

POJ 1753

#include<iostream>
usingnamespace std;
bool map[6][6],f=0;
int dir[5][2]={{0,0},{0,1},{1,0},{-1,0},{0,-1}};
int step;
//翻转操作
void roll(int row,int col){
for(int i=0;i<5;i++){
int x=row+dir[i][0];
int y=col+dir[i][1];
map[x][y]=!map[x][y];
}
}
//判断
bool judge(){
int i,j;
for(i=1;i<=4;i++)
for(j=1;j<=4;j++)
if(map[i][j]!=map[1][1])
return0;
return1;
}
/*************************************************************/
bool dfs(int row,int col ,int dep){
if(dep==step){
f = judge();
return0;
}//由后面可以发现dfs的走向是从左到右,从上到下的
//所以当row==5的时候也已经实现啦
if(f||row==5)return1;
//翻转一次
roll(row,col);
if(col<4)//当dfs到最右端的时候(即col==4),需要
//控制dfs的走向转为第二行第一个
dfs(row,col+1,dep+1);
else dfs(row+1,1,dep+1);
//再原地翻转即还原
//一定要理解,dep不变与dep+1的区别
roll(row,col);
if(col<4)
dfs(row,col+1,dep);
else dfs(row+1,1,dep);
return0;
}
int main(){
int i,j;
char c;
for(i=1;i<=4;i++){
for(j=1;j<=4;j++){
cin>>c;
if(c=='b')map[i][j]=1;
else map[i][j]=0;
}
}
for(step=0;step<=16;step++){
dfs(1,1,0);
if(f)break;
}
if(f)cout<<step<<endl;
else cout<<"Impossible"<<endl;
return0;
}


题目:

Flip Game

Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 13306Accepted: 5693
Description
Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the other one is black and each piece is lying either it's black or white side up. Each round you flip 3 to 5 pieces, thus changing the color of their upper side from black to white and vice versa. The pieces to be flipped are chosen every round according to the following rules:

Choose any one of the 16 pieces.

Flip the chosen piece and also all adjacent pieces to the left, to the right, to the top, and to the bottom of the chosen piece (if there are any).



Consider the following position as an example:

bwbw
wwww
bbwb
bwwb
Here "b" denotes pieces lying their black side up and "w" denotes pieces lying their white side up. If we choose to flip the 1st piece from the 3rd row (this choice is shown at the picture), then the field will become:

bwbw
bwww
wwwb
wwwb
The goal of the game is to flip either all pieces white side up or all pieces black side up. You are to write a program that will search for the minimum number of rounds needed to achieve this goal.
Input
The input consists of 4 lines with 4 characters "w" or "b" each that denote game field position.
Output
Write to the output file a single integer number - the minimum number of rounds needed to achieve the goal of the game from the given position. If the goal is initially achieved, then write 0. If it's impossible to achieve the goal, then write the word "Impossible" (without quotes).
Sample Input
bwwb
bbwb
bwwb
bwww

Sample Output
4


还有一种写法:

#include<iostream>
using namespace std;
char map[4][4];// 地图
int maxNum,n;
bool CanPut(int row, int col)
{//测试是否可以放置碉堡到row行col列处,因为位置是从小到大前进的,因此只需要测试比待测试点小的位置
int i;
//测试col列上是否有面对面的碉堡
for (i = row - 1; i >= 0; --i)
{
if (map[i][col] == 'O') return false;
if (map[i][col] == 'X') break;
}
//测试row行上是否有面对面的碉堡
for (i = col - 1; i >= 0; --i)
{
if (map[row][i] == 'O') return false;
if (map[row][i] == 'X') break;
}
return true;
}
void Solve(int k,int curNum)
{
int x,y;
if(k==n*n)
{//到最后一个了
if(curNum>maxNum)
{//保存当前遍历路径找到的最大值
maxNum=curNum;
return;
}
}
else
{
x=k/n;//行号
y=k%n;//列号
if((map[x][y]=='.')&&(CanPut(x,y)==true))
{//当前点是空白处,并且可以放置碉堡
map[x][y]='O';//放置碉堡
Solve(k+1,curNum+1);//递归进入下一个位置
map[x][y]='.';//回溯
}
//当前点不能放置或回溯回来
Solve(k+1,curNum);
}
}
int main()
{
int i,j;
while(cin>>n&&n!=0)
{
//输入地图
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
cin>>map[i][j];
}
}
maxNum=0;//最多可能放置的数目
//开始深搜,起点设置为左上角
Solve(0,0);
cout<<maxNum<<endl;
}
return 0;
}


题意:
用N*N的矩阵给出一个城市的地图,在里面摆城堡,每个城堡所在的行和列上不能有其他城堡,除非他们之间有墙,有墙的位置为‘X’,其他位置为‘.’,问最多能放多少个城堡



Sample input:

4
.X..
....
XX..
....
2
XX
.X
3
.X.
X.X
.X.
3
...
.XX
.XX
4
....
....
....
....
0

Sample output:

5
1
5
2
4
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: