POJ1321棋盘问题(AC2)

棋盘问题
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 29595 Accepted: 14667

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
 
    #define _CRT_SECURE_NO_WARNINGS  
      
    #include <stdio.h>  
      
    //做到一半就卡住了,原因在于如果两个for循环,先扫行再扫列,扫完第一行,再扫第二行,那这样就会有重复的耶,后来想了个办法,输入有行号,按行号来  
      
    /*第一次提交lte超时 之前加了个for (i = hang; i < n; i++) 这个循环是不需要的,*/  
      
    #define MAXINT 10  
      
    int n = 0;  
    int k = 0;  
      
    int  ans = 0;  
    char map[MAXINT][MAXINT];  
    int visithang[MAXINT];  
    int visitlie[MAXINT];  
      
    void init()  
    {  
        int i = 0;  
        int j = 0;  
        for (i = 0; i < n; i++)  
        {  
            for (j = 0; j < n; j++)  
            {  
                map[i][j]   = '\0';  
            }  
            visithang[i] = 0;  
            visitlie[i] = 0;  
        }  
      
        ans = 0;  
        return;  
    }  
      
    void dfs(int hang,int num)  
    {  
        //int i = 0;  
        int j = 0;   
        if (num == k)  
        {  
            ans += 1;  
            return;  
        }  
        if (hang >n) return;  
        if ((n-hang) < (k-num)) return;//剩下的行数还不够棋子的个数,直接return 
        //for (i = hang; i < n; i++)  
        //{  
            for (j = 0; j < n;j++)  
            {  
                //if (1 == visithang[hang]) break;  
                if (1 == visitlie[j])  continue;  
                if ('.' == map[hang][j]) continue;  
                //visithang[i] = 1;  
                visitlie[j] = 1;  
                dfs(hang+1,num + 1);  
                //回溯  
                //visithang[i] = 0;  
                visitlie[j]  = 0;  
            }  
        //}  
		/*4 2
			#...
			##..
			...#
			..#.
		像这样的数据第一行第二行便利完,还得遍历第一行,第三行啊	*/
		dfs(hang+1,num );  //这个很关键,自己写的时候还是会有点参考,就是这样的,num不+1表示hang这行没放,比如第0行然后第1行,第一行不放就是第2行
        return;  
    }  
      
    int main()  
    {  
        int i = 0;  
        int j = 0;  
        int num = 0;  
        freopen("input.txt","r",stdin);  
        while (2 == scanf("%d %d", &n, &k) && (-1 != n) && (-1 != k))  
        {  
            init();  
            for (i = 0; i < n;i++)  
            {  
                    scanf("%s", &map[i]);  
            }  
            for (i = 0; i < n; i++)  
            {  
                for (j = 0; j < n; j++)  
                {  
                    if ('#' == map[i][j]) ans++;  
                }  
            }  
      
            if (1 != k)  
            {  
                ans = 0;  
                dfs(0,0); //从0行开始,后面那个是放置的棋子个数  
            }  
            printf("%d\n",ans);  
        }  
        return 0;  
    } 
 
 
//第二次就这样糊里糊涂的通过了
#include <stdio.h>
//POJ1321棋盘问题
#define MAXINT 10
char map[MAXINT][MAXINT];
int ans = 0;
int n = 0;
int w = 0;
int visithang[MAXINT]; //表示哪行已经被占领了
int visitlie[MAXINT];//表示哪列已经被占领了
//棋盘问题不是一个很好解决的问题吗?怎么自己也卡盒了。。。。自己学了那么久就到底是在干嘛,今天开始要复习复习复习。。。
//这样就一次AC了,不相信啊不相信
void init()
{
	int i = 0;
	int j = 0;
	for (i = 0; i < MAXINT; i++)
	{
		for (j = 0; j < MAXINT; j++)
		{
			map[i][j] = '\0';
		}
		visithang[i] = 0;
		visitlie[i]  = 0;
	}
	ans = 0;
	return;
}

void dfs(int x, int y, int num) //num表示放了几个棋子了
{
	int i = 0;
	int j = 0;
	if ((x<0)||(x>=w)||(y<0)||(y>=w)) return;
	if (num == n)
	{
		ans += 1;
		return;
	}
	

	for (i = x; i < w; i++)
	{
		for (j = 0; j < w; j++)
		{
			if (visithang[i]) continue;
			if (visitlie[j]) continue;
			if ('.' == map[i][j]) continue;
			visithang[i] = 1;
			visitlie[j] = 1;
			dfs(i,j,num+1);
			visithang[i] = 0;
			visitlie[j] = 0;
		}
	}

	//但是这样写不对耶。。。会有错误答案
	//dfs(x+1, 0, 0); //防止有多行的出现,即行号比棋子多的情况
	return;
}


//n <= 8 , k <= n因为最大只有8所以可以用DFS
int main()
{
	int i = 0;
	int j = 0;
	freopen("input.txt","r",stdin);
	while ((2 == scanf("%d %d",&w,&n))&&(-1 != w)&&(-1 != n))
	{
		init();
		for (i = 0; i < w;i++)
		{
			scanf("%s", &map[i]);
		}
		dfs(0, 0, 0);
		printf("%d\n",ans);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值