zoukankan      html  css  js  c++  java
  • UVA 1603 Square Destroyer

    题意:

      给定一个火柴棒拼成的方格阵,然后去掉一些火柴棒,问至少再去掉几根火柴棒能够让图中一个正方形都没有。

    思路:

    1. 由于题目中给定了 n 的范围,2 * n * (n + 1) <= 60 -> 所以能够保证所有的火柴用 long long的位运算表示;

    2. 启发式函数 h 的计算需要考量:如果删除了某个方阵的一个边,则能够保证 h(s1) <= h(s2) + C(s1, s2),其中 C(s1, s2) = 1,h(s1) - h(s2) <= 1;

    3. 各种位运算的范围要明确,如 1<<i 前面要加上long long 修饰方能得到正确的结果

    代码:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int INFS = 0x7fffffff;
    int N,C,E,bound;
    long long squ[100],xiao[6][6];
    bool flag;
    long long get2(int i)
    {
    return ((long long)1<<(i-1));
    }
    int getnumber1(int i,int j)
    {
    return (2*N+1)*(i-1)+j;
    }
    int getnumber2(int i,int j)
    {
    return (2*N+1)*(i-1)+j+N;
    }
    void build()
    {
    C=0;
    memset(xiao,0,sizeof(xiao));
    int i,j;
    for(i=1;i<=N;i++)
    for(j=1;j<=N;j++)
    {
    xiao[i][j]|=get2(getnumber1(i,j))|get2(getnumber1(i+1,j));
    xiao[i][j]|=get2(getnumber2(i,j))|get2(getnumber2(i,j+1));
    squ[C++]=xiao[i][j];
    }
    for(int size=2;size<=N;size++)
    {
    for(i=1;i+size-1<=N;i++)
    {
    for(j=1;j+size-1<=N;j++)
    {
    squ[C]=0;
    for(int a=0;a<size;a++)
    {
    for(int b=0;b<size;b++)
    {
    squ[C]^=xiao[i+a][j+b];;
    }
    }
    C++;
    }
    }
    }
    }
    int dfs(long long state,int de)
    {
    int h=0;
    long long u=0,s=state;
    for(int i=0;i<C;i++)
    {
    if((s&squ[i])==squ[i])
    {
    h+=1;
    s^=squ[i];
    if(u==0)
    u=squ[i];
    }
    }
    if(h==0)
    {
    flag=true;
    return de;
    }
    if(de+h>bound)
    return de+h;
    int news=INFS;
    for(int i=1;i<=E;i++)
    {
    if(u&get2(i))
    {
    int b=dfs(state^get2(i),de+1);
    if(flag)
    return b;
    news=min(b,news);
    }
    }
    return news;
    }
    int main()
    {
    int t;
    scanf("%d",&t);
    while(t--)
    {
    scanf("%d",&N);
    build();
    E=2*N*(N+1);
    int k;
    long long state=((long long)1<<E)-1;
    scanf("%d",&k);
    for(int i=0;i<k;i++)
    {
    int x;
    scanf("%d",&x);
    state^=get2(x);
    }
    flag=false;
    bound=0;
    while(!flag)
    {
    bound=dfs(state,0);
    }
    printf("%d ",bound);
    }
    }
  • 相关阅读:
    [GIT]指定分支下创建分支
    [架构]辨析: 高可用 | 集群 | 主从 | 负载均衡 | 反向代理 | 中间件 | 微服务 | 容器 | 云原生 | DevOps
    [Linux]常用命令之【vi/grep/find】
    [Linux]常用命令之【netstat/ps/lsof/ss/kill/】
    [Linux]常用命令之【nl/sed/awk/wc/xargs】
    移动端vw页面适配方案在vue项目中的应用
    关于跨域,你应该知道的
    关于call、apply和bind,请看这篇
    JavaScript数组常用API方法汇总
    JS浅拷贝与深拷贝实现方式
  • 原文地址:https://www.cnblogs.com/137033036-wjl/p/4871061.html
Copyright © 2011-2022 走看看