uva1603

题目描述:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51165

/*
solution:
    可以用迭代加深算法作为框架。搜索对象主要有两种:一是正方形,而是火柴。
    个人采取前者。

date:2016/5/15
*/
#include 
#include 
#include 

using namespace std;
const int maxn = 60;
int s, n, k, rec_size[maxn], rec_full_size[maxn], contain[maxn][maxn];  //contain[i][j] = 1代表编号为i的正方形包含了编号为j的火柴
int sticks[maxn], maxd; //stick[i] = 1代表编号为i的火柴存在

inline int get_sticks() {
    return 2 * n * (n + 1);
}

inline int get_horizental(int r, int c) {
    return (r - 1) * (2 * n + 1) + c;
}

inline int get_vertical(int r, int c) {
    return n * (2 * r - 1) + r + c - 1;
}

int get_rec_num() {
    for(int i = 1; i < s; i++)
        if(rec_size[i] == rec_full_size[i])
            return i;
    return 0;
}

void dfs(int d) {
    if(d >= maxd)   return;
    if(!get_rec_num()) {
        maxd = d;
        return;
    }

    int k = get_rec_num();  //选择一个正方形拿掉其中边上一根火柴
    for(int i = 1; i <= get_sticks(); i++) {
        if(contain[k][i]) {
            for(int j = 1; j < s; j++)
                if(contain[j][i])   rec_size[j]--;

            dfs(d + 1);

            for(int j = 1; j < s; j++)
                if(contain[j][i])   rec_size[j]++;
        }
    }
}

int main()
{
    //freopen("input.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= get_sticks(); i++) sticks[i] = 1;
        int v;
        while(k--) {
            scanf("%d", &v);
            sticks[v] = 0;
        }

        //初始化,构建各个正方形
        s = 1;
        memset(contain, 0, sizeof(contain));
        for(int len = 1; len <= n; len++) {
            for(int i = 1; i <= n - len + 1; i++)
            for(int j = 1; j <= n - len + 1; j++) {
                rec_size[s] = 0;
                rec_full_size[s] = 4 * len;
                for(int k = 0; k < len; k++) {
                    int a = get_horizental(i, j + k);   //上行
                    int b = get_horizental(i + len, j + k); //下行
                    int c = get_vertical(i + k, j); //左列
                    int d = get_vertical(i + k, j + len);   //右列

                    contain[s][a] = 1;
                    contain[s][b] = 1;
                    contain[s][c] = 1;
                    contain[s][d] = 1;

                    rec_size[s] += (sticks[a] + sticks[b] + sticks[c] + sticks[d]);
                }
                s++;
            }
        }

        //迭代加深
        maxd = n * n;
        dfs(0);
        printf("%d\n", maxd);
    }
    return 0;
}

你可能感兴趣的:(uva,OJ,=====各种搜索=====)