ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

POJ - 1084 Square Destroyer(IDA*算法)

2022-01-18 13:00:37  阅读:176  来源: 互联网

标签:1084 Destroyer int ++ 正方形 depth used square Square


POJ - 1084 Square Destroyer

在这里插入图片描述

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

const int N = 61;      // 网格最大是 5 * 5 的,其中最多会有 5 * (5 + 1) * 2 = 60 个正方形,所以要开到 61
int n, idx;            // n 为网格规模,idx 为正方形数量
int max_depth;         // IDA* 的 max_depth
vector<int> square[N]; // 存每个正方形边上的火柴的编号
bool used[N];          // 存每个火柴是否已经被破坏
// 新加一个左上角坐标为 (r, c),边长为 len 的正方形
void add(int r, int c, int len)
{
    int d = n << 1 | 1;  // 由于用到的 2n + 1 比较多,这里先用一个变量代替掉 2n + 1
    vector<int> &s = square[idx];
    s.clear(); // 有多组测试数据,需要上一组数据的内容清空
    for (int i = 0; i < len; i ++ )
    {
        s.push_back(1 + r * d + c + i);               // 上边第 i 个
        s.push_back(1 + (r + len) * d + c + i);       // 下边第 i 个
        s.push_back(1 + n + r * d + c + i * d);       // 左边第 i 个
        s.push_back(1 + n + r * d + c + i * d + len); // 右边第 i 个
    }
    idx ++ ;
}
// 判断正方形 s 是否完整
bool check(vector<int> &s)
{
    for (int i = 0; i < (int)s.size(); i ++ )
        if (used[s[i]]) 
			return false; // 如果其中有一条边已经被破坏了,那么说明不完整
    return true; // 如果每条边都没被破坏,说明完整
}
// 估价函数
int f()
{
    static bool backup[N]; // 由于要改动 used,需要先新建一个备份数组
    memcpy(backup, used, sizeof used); // 将 used 复制到备份数组中
    int res = 0;
    for (int i = 0; i < idx; i ++ ) // 枚举所有正方形
        if (check(square[i]))       // 如果某个正方形是完整的,
        {
            res ++ ;                // 那么 res ++ ,并将该正方形所有的边都删去
            for (int j = 0; j < (int)square[i].size(); j ++ )
                used[square[i][j]] = true;
        }
    memcpy(used, backup, sizeof used); // 复制回来
    return res;
}

// IDA*
bool dfs(int depth)
{
    if (depth + f() > max_depth) return false;
    for (int i = 0; i < idx; i ++ ) // 枚举所有的正方形
        if (check(square[i]))       // 如果第 i 个正方形还没被破坏
        {// 那么枚举该正方形的所有边编号,去掉该边并继续爆搜
            for (int j = 0; j < (int)square[i].size(); j ++ )
            {
                used[square[i][j]] = true;
                if (dfs(depth + 1)) return true;
                used[square[i][j]] = false;
            }
            return false;// 如果每条边都爆搜不成功,那么说明删掉 max_depth 个火柴无法破坏该正方形
        }
    return true; // 如果所有的正方形都被破坏了,返回 true
}

int main()
{
    int T;scanf("%d",&T);
    while (T -- )
    {
        scanf("%d", &n), idx = 0; // 初始化 idx
        memset(used, false, sizeof used); // 初始化 used
        for (int len = 1; len <= n; len ++ ) // 枚举 len, r, c,预处理每个正方形
            for (int r = 0; r + len <= n; r ++ )
                for (int c = 0; c + len <= n; c ++ )
                    add(r, c, len);
        int k;scanf("%d", &k);
        while (k -- )  // 读入所有已经被破坏的边
        {
            int x;scanf("%d", &x);
            used[x] = true;
        }
        max_depth = 0; // IDA*
        while (!dfs(0)) max_depth ++ ;
        printf("%d\n", max_depth);
    }
    return 0;
}

标签:1084,Destroyer,int,++,正方形,depth,used,square,Square
来源: https://blog.csdn.net/qq_52792570/article/details/122557644

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有