習題7-10:守衛棋盤(dfs迭代加深)

習題7-10:守衛棋盤
給出m*n棋盤上的目標點,求最少用幾個皇后可以守衛所有目標點。
類似八皇后做法,2維數組標記行、列、主對角線、副對角線。
有個加速的技巧,測試之後發現10*10的棋盤全部守衛至少需要5個,所以上限就是5,當maxd等於5時直接輸出,不進行搜索。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
#include<set>
#include<queue>
#include<map>
#include<stack>
#include<vector>
#include<list>
#include<deque>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
const double eps = 1e-6;
const int INF = 1 << 30;
const int dir[4][2] = {1,0,0,1,0,-1,-1,0};
int n, m, maxd;
bool Map[12][12], vis[4][50];
bool input()
{
    cin >> n;
    if(!n)return false;
    cin >> m;
    char x;
    memset(Map, 0, sizeof(Map));
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
            cin >> x;
            if(x == 'X')Map[i][j] = 1;
        }
    }
    return true;
}
bool judge()
{
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
            if(Map[i][j] && !vis[0][i] && !vis[1][j] && !vis[2][i + j] && !vis[3][i - j + 11])return false;
        }
    }
    return true;
}
bool dfs(int d, int i, int j)
{
    if(d == maxd)
    {
        if(judge())return true;
        return false;
    }
    for(; i < n; i++)
    {
        for(; j < m; j++)
        {
            bool tmp1 = vis[0][i], tmp2 = vis[1][j], tmp3 = vis[2][i + j], tmp4 = vis[3][i - j + 11];
            vis[0][i] = vis[1][j] = vis[2][i + j] = vis[3][i - j + 11] = 1;
            if(dfs(d + 1, i, j + 1))return true;
            vis[0][i] = tmp1;
            vis[1][j] = tmp2;
            vis[2][i + j] = tmp3;
            vis[3][i - j + 11] = tmp4;
        }
        j = 0;
    }
    return false;
}
int main()
{
    int cases = 0;
    while(input())
    {
        for(maxd = 0; maxd < 5; maxd++)
        {
            memset(vis, 0, sizeof(vis));
            if(dfs(0, 0, 0))break;
        }
        printf("Case %d: %d\n", ++cases, maxd);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章