uva1603

这篇博客详细介绍了UVA在线判题系统中编号为1603的编程题目,包括问题描述、解题思路、算法实现及可能遇到的陷阱,帮助读者理解和解决该问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

date:2016/5/15
*/
#include <iostream>
#include <cstdio>
#include <cstring>

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值