POJ -棋盘问题

棋盘问题
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 60815   Accepted: 29135

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

思路:典型回溯水题,不过这一次学到了不存小地图方法,就是每次存棋盘的位置就行了。而且这个样子的话,相当于给每个位置标好了号码,这样就可以吧问题转变成组合问题,我们拿个栗子说明

输入样例:
3 2
#..
.#.
..#
-1 -1

输出样例:
3

很明显的1,2,3,然后从中选两个,方式就是1先找后面能满足条件的,有1和2、1和3;然后从2往后找,有2和3;然后从3往后找,结束。

注意:提交的时候WA了,试试换个提交方式!!!随便放一段毒代码

#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>
#define ll long long
using namespace std;

int pa[100], pb[100];              //棋盘摆放    #棋盘区域    .空白区域 
int n, k;                        //表明是n*n的矩阵 摆放k个棋子 
int vx[100] = { 0 };                 //走过的行的位置
int vy[100] = { 0 };                 //走过的列的位置 
ll sum = 0;                    //摆放的方法 
int ss;                         //记录#的个数 
int visit[1000] = { 0 };                 //走过的点 

void dfs(int i, int j){
    if (j == k){
        sum++;
    }
    else{
        for (int l = i; l<ss; ++l){
            if (visit[l] == 0 && vx[pa[l]] == 0 && vy[pb[l]] == 0){
                vx[pa[l]] = 1;
                vy[pb[l]] = 1;
                visit[l] = 1;
                dfs(l + 1, j + 1);
                vx[pa[l]] = 0;
                vy[pb[l]] = 0;
                visit[l] = 0;
            }
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    while (~scanf("%d%d",&n,&k)) {
        getchar();
        if (n == -1 && k == -1)break;
        sum = 0;
        ss = 0;
        memset(vx, 0, sizeof(vx));
        memset(vy, 0, sizeof(vy));
        memset(visit, 0, sizeof(visit));

        for (int i = 0; i<n; ++i){
            for (int j = 0; j<n; ++j){
                char temp;
                cin >> temp;
                if (temp == '#'){
                    pa[ss] = i;                   //把棋盘区域(i,j)加进数组 
                    pb[ss++] = j;
                }
            }
        }
        dfs(0, 0);                                 //从第一个为#的点开始,一开始摆放的棋子数为0; 
        cout << sum << endl;
    }
    return 0;
}
C++提交AC,G++WA

以下AC代码:

#include<iostream>
#include<string.h>
using namespace std;
int n, k, sum, len;
int pa[100], pb[100], vx[10] = { 0 }, vy[10] = { 0 }, vis[100] = { 0 };
void dfs(int s, int c)
{
    if (c > k)return;
    if (c == k)sum++;
    else {
        for (int i = s; i < len;i++)
        if (vis[i] == 0 && vx[pa[i]] == 0 && vy[pb[i]] == 0){
            vis[i] = vx[pa[i]] = vy[pb[i]] = 1;
            dfs(i + 1, c + 1);
            vis[i] = vx[pa[i]] = vy[pb[i]] = 0;
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    while (cin >> n >> k, n != -1 && k != -1){
        len = sum = 0;
        
        for (int i = 0; i < n;i++)
        for (int j = 0; j < n; j++){
            char ch; cin >> ch;
            if (ch == '#'){
                pa[len] = i;
                pb[len++] = j;
            }
        }
        dfs(0, 0);
        cout << sum << endl;
    }
    return 0;
}

 

posted @ 2018-05-09 21:23  我只有一件白T恤  阅读(206)  评论(0编辑  收藏  举报