zoukankan      html  css  js  c++  java
  • UVa 1603 破坏正方形

    https://vjudge.net/problem/UVA-1603

    题意:有一个火柴棍组成的正方形网格,计算至少要拿走多少根火柴才能破坏所有正方形。

    思路:从边长为1的正方形开始遍历,将正方形的边长和它的实际火柴数保存起来。之后dfs搜索。

    #include<iostream>
    #include<cstring>
    using namespace std;
    
    const int maxn = 60;
    
    int n, m,best,s;
    int map[maxn],size[maxn],fullsize[maxn];
    int contins[maxn][maxn];
    
    int row_match(int x, int y)   //
    {
        return (2 * n + 1)*x + y;
    }
    
    int col_match(int x, int y)  //
    {
        return (2 * n + 1)*x + n + y;
    }
    
    int edges()  //计算火柴根数
    {
        return 2*n*(n + 1);
    }
    
    void init()
    {
        int ans;
        cin >> n >> m;
        //初始化网格
        for (int i = 0; i < edges(); i++)
            map[i] = 1;
        while (m--)
        {
            cin >> ans;
            map[ans - 1] = 0;
        }
        s = 0;  //s用来为正方形编号
        memset(contins, 0, sizeof(contins));
        for (int i = 1; i <= n;i++)  //正方形的边长,从1开始到n
        for (int x = 0; x <= n - i;x++) //正方形左上角的x坐标
        for (int y = 0; y <= n - i; y++) //正方形左上角的y坐标
        {
            size[s] = 0;
            fullsize[s] = 4 * i;  //第s个正方形的边长
            //cout << fullsize[s] << "*" << endl;
            for (int j = 0; j < i; j++)
            {
                int a = row_match(x, y + j);      
                int b = row_match(x + i, y + j);  
                int c = col_match(x + j, y);     
                int d = col_match(x + j, y + i);  
                contins[s][a] = 1;  //储存正方形的边
                contins[s][b] = 1;
                contins[s][c] = 1;
                contins[s][d] = 1;
                size[s] += map[a] + map[b] + map[c] + map[d];  
            }
            s++;
        }
    }
    
    int find_sqware()
    {
        for (int i = 0; i < s;i++)
        if (fullsize[i] == size[i])     return i; //找到未被破坏的正方形
        return -1;
    }
    
    void dfs(int dep)
    {
        if (dep >= best) return;
        int k = find_sqware();
        if (k == -1) //每个正方形都已经被破坏
        {
            best = dep;
            return;
        }
        for (int i = 0; i < edges(); i++)
        {
            if (contins[k][i])
            {
                for (int j = 0; j < s;j++)
                if (contins[j][i])    size[j]--;  //破坏,边的数量减少
                dfs(dep + 1);
                for (int j = 0; j < s;j++)  //回溯
                if (contins[j][i])  size[j]++;
            }
        }
    }
    int main()
    {
        //freopen("D:\txt.txt", "r", stdin);
        int t;
        cin >> t;
        while (t--)
        {
            init();
            best = n*n;
            dfs(0);
            cout << best << endl;
        }
        return 0;
    }
  • 相关阅读:
    C语言ll作业01
    C语言寒假大作战04
    C语言寒假大作战03
    C语言寒假大作战02
    C语言寒假大作战01
    C语言I作业12—学期总结
    C语言I博客作业11
    C语言I博客作业10
    C语言I博客作业08
    C语言寒假大作战02
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6349947.html
Copyright © 2011-2022 走看看