1603 - Square Destroyer

The left figure below shows a complete 3x3 grid made with 2x(3x4) (=24) matchsticks. The lengths of all matchsticks are one. You can find many squares of different sizes in the grid. The size of a square is the length of its side. In the grid shown in the left figure, there are 9 squares of size one, 4 squares of size two, and 1 square of size three.

Each matchstick of the complete grid is identified with a unique number which is assigned from left to right and from top to bottom as shown in the left figure. If you take some matchsticks out from the complete grid, then some squares in the grid will be destroyed, which results in an incomplete 3×3 grid. The right figure illustrates an incomplete 3×3 grid after removing three matchsticks numbered with 12, 17 and 23. This removal destroys 5 squares of size one, 3 squares of size two, and 1 square of size three. Consequently, the incomplete grid does not have squares of size three, but still has 4 squares of size one and 1 square of size two.
这里写图片描述
As input, you are given a (complete or incomplete) n × n grid made with no more than 2n(n+1) matchsticks for a natural number n 5 . Your task is to compute the minimum number of matchsticks taken out to destroy all the squares existing in the input n × n grid.
Input

The input consists of T test cases. The number of test cases (T) is given in the first line of the input file. Each test case consists of two lines: The first line contains a natural number n , not greater than 5, which implies you are given a (complete or incomplete) n × n grid as input, and the second line begins with a nonnegative integer k , the number of matchsticks that are missing from the complete n × n grid, followed by k numbers specifying the matchsticks. Note that if k is equal to zero, then the input grid is a complete n × n grid; otherwise, the input grid is an incomplete n × n grid such that the specified k matchsticks are missing from the complete n × n grid.
Output

Print exactly one line for each test case. The line should contain the minimum number of matchsticks that have to be taken out to destroy all the squares in the input grid.
Sample Input

2
2
0
3
3 12 17 23
Sample Output

3
3
我有话说:
主算法框架为迭代加深搜索。搜索对象为方格,寻找一个完整的方格,枚举在边上破坏一根火柴可能的情况,并进行剪枝。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
const int maxm=60;//1+4+9+16+25=55
const int maxs=60;//2*5*6=60;
int best;
int n,exists[maxm];//火柴
int s, size[maxs], fullsize[maxs], contains[maxs][maxm];//正方形
inline int row_match(int x, int y) {
  return (2*n+1)*x+y;
}

inline int col_match(int x, int y) {
  return (2*n+1)*x+n+y;
}

// number of matches in a full n*n grid
inline int match_count(int n) {
  return 2*n*(n+1);
}
void Init()
{
    int m,v;
    scanf("%d%d",&n,&m);
    for(int i=0;i<match_count(n);i++)
        exists[i]=1;
    while(m--)
    {
        scanf("%d",&v);
        exists[v-1]=0;
    }
    s=0;
    memset(contains,0,sizeof(contains));
    for(int i=1;i<=n;i++)//所找到的正方形的边长
    {
        for(int x=0;x<=n-i;x++)
        {
            for(int y=0;y<=n-i;y++)
            {
                size[s]=0;
                fullsize[s]=4*i;
                for(int j=0;j<i;j++)
                {
                    //尝试以左上角为(0,0),向右向下为正向,每个火柴交界点为一个店,一根火柴的长度为单位长度
                    //这样就可以按照row_match(横放的火柴),col_match(竖放的火柴)对火柴进行编号,从0开始到2*n*(n+1)-1
                    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); //右
                    contains[s][a]=1;//该正方形的边界是否包括该火柴
                    contains[s][b]=1;
                    contains[s][c]=1;
                    contains[s][d]=1;
                    size[s]+=exists[a]+exists[b]+exists[c]+exists[d];
                }
                s++;
            }
        }
    }
}
int find_square() 
{
    for(int i=0;i<s;i++)
        if(fullsize[i]==size[i])return i;
    return -1;
}
void dfs(int d)
{
    if(d>=best)return;
    int k=find_square();
    if(k==-1)
    {
        best=d;
        return;
    }
    for(int i=0;i<match_count(n);i++)
    {
        if(contains[k][i])
        {
            for(int j=0;j<s;j++)
                if(contains[j][i])size[j]--;
            dfs(d+1);
            for(int j=0;j<s;j++)
                if(contains[j][i])size[j]++;
        }
    }
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        Init();
        best=n*n;
        dfs(0);
        printf("%d\n",best);
    }
    return 0;
}

匹配下面左边的图显示了一个完整的3 x3网格由2 x(3 x4)(= 24)火柴棍。所有的火柴棍的长度。你可以找到许多不同大小的正方形网格。大小的平方是自己一边的长度。在左侧所示的网格图中,有9个方块的大小,4广场大小两种,1平方大小的三个。
完整的网格的每个火柴标识分配一个惟一的编号,从左至右,从上到下,左边的图所示。如果你需要一些火柴从完整的网格,然后一些正方形网格将被摧毁,导致一个不完整的3×3网格。正确的图展示了一个不完整的3×3网格后删除三个火柴编号12,17日和23日。去除破坏5方格的大小,3广场大小两种,1平方大小的三个。因此,不完整的网格没有广场大小三个,但仍有4个方块的大小,1平方大小的两个。
作为输入,你给出了一个(完整或不完整)n×n网格由不超过2 n(n + 1)火柴一个自然数n 5。你的任务是计算最小数量的火柴棍了摧毁所有的广场现有输入n×n网格。
输入
输入包括T测试用例。测试用例的数量(T)中给出了输入文件的第一行。每个测试用例包含两行:第一行包含一个自然数n,不大于5,这意味着你有一个(完整或不完整)n×n网格作为输入,第二行开始与一个非负整数k,火柴棍的数量缺少完整的n×n网格,其次是k数字指定火柴棍。注意,如果k等于零,那么输入网格是一个完整的n×n网格;否则,输入网格是一个不完整的n×n网格,这样指定的k火柴棍缺少完整的n×n网格。
输出
为每个测试用例完全打印一行。线应该包含的最小数量的火柴棍,摧毁所有的方块输入电网。
样例输入
2
2
0
3
3 12 1723
样例输出
3
3

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值