题意:

       有一个城镇,是4*4的大小的,然后你控制一块云彩,2*2的,你每天可以有9种走的方法,上下左右,或者不动,走的时候可以走1或者2步,云彩所在的地方肯定会下雨,然后给你做多365天的安排,要求某些日子的某些城镇不能下雨(因为有**节日),还有任何地方都不能有连续超过6天不下雨。

思路:

       首先9种走法,做多连续六点不下雨,这个可以直接DFS深搜,(BFS不知道行不行,没试过,主要担心的是内存,反正目测BFS队列QUEUE占用的内存太大),如果不优化的话的话时间复杂度可是9^365根本受不了啊,然后就是考虑优化,也就是mark走过的状态,关键是怎么标记这个状态,一开始我是想找16个素数,然后根据每个格子的步数去计算每个16个步数得到的一个特别值去hash状态,可以失败了,找素数的方法不行,举个例子 3 * 7 + 7 * 3 = 7 * 3 + 3 * 7,然后就是考虑状态压缩,可是按照最笨的放发的话状态压缩的9^16中状态,后来我自己优化了下,还是9^12种状态,还是不行,后来看了别人的解释,一开始有疑惑,想了好久才说服自己,说下标程,可以只考虑四个点,假如当前用云彩的左上角表示云彩,那么我们只要考虑的四个点就是
1 1 ,1 3 ,3 1,3 3也就是云彩在四个角落的时候的坐标,判断下雨天数的时候可以只判断这四个,还有mark的时候也是mark[t][n][a][b][c][d] t 天数,a云彩当前位置(只记录左上角,离散化之后就9个),a b c d分别是当前那4个关键位置连续没下雨的天数,然后就直接DFS就行了,下面解释下为什么这样是对的:

(1)充分性 : 只要这四个点都满足天数不大于7 那么全图肯定都满足,这个自己看下就知道了,因为把图分成四块,这四个关键点肯定是每一个块中连续不下雨天数最长的。

(2)必要性 : 如果全图都满足连续不下雨情况,那么这四个关键点必然满足,因为要想让(1 ,1) ,(1 ,4) ,(4 ,1) ,(4 ,4)都满足,那么必须走这4个关键点,别的点照顾不到这。

(3)还有就是只用这四个点代表唯一性是否正确,这个我犹豫了好久,就是这个地方一开始怎么也想不明白,现在说下我目前的理解。

假如当前状态

1111 2222        1111 2222   如果按照上面的那个方法mark必须证明这两个状态是一

1111 2222        1111 2222   个状态,我的理解是四个关键位置的连续不下雨天数一定

3333 4444        3332 4443   比自己所在的模块的所有天数都大,无论什么时候,那么

3333 4444        3332 4443   也就是说如果以后出现问题肯定是这四个最大的中的某个

                             出现问题,也就是别的点永远都只是陪衬,所以 陪衬的点

                             怎么样不会影响总的状态以及最终的趋势,所以这种mark                               的方法是正确的,这个是我自己的理解。

#include<stdio.h>

#include<string.h>

int DAY[367];

bool mark[366][10][8][8][8][8];

int ys[12] = {0 ,1 ,2 ,3 ,0 ,4 ,5 ,6 ,0 ,7 ,8 ,9};

int dir[9][2] = {0 ,0 ,0 ,1 ,0 ,-1 ,1 ,0 ,-1 ,0 ,0 ,2 ,0 ,-2 ,2 ,0 ,-2 ,0};

int OK ,T;

bool ok(int t ,int x ,int y ,int a[])

{

    int aa = (x - 1) * 4 + y;

    int bb= (x - 1 + 1) * 4 + y;

    int cc = (x - 1) * 4 + y + 1;

    int dd = (x - 1 + 1) * 4 + y + 1;

    if(x < 1 || x > 3 || y < 1 || y > 3)

    return 0;

    if(a[1] >= 7 || a[2] >= 7 || a[3] >= 7 || a[4] >= 7)

    return 0;

    if(((1 << aa) & DAY[t]) || ((1 << bb) & DAY[t]) || ((1 << cc) & DAY[t]) || ((1 << dd) & DAY[t]))

    return 0;

    if(mark[t][ys[aa]][a[1]][a[2]][a[3]][a[4]]) return 0;

    return 1;

}

void DFS(int t ,int x ,int y ,int a[])

{

    if(t == T) OK = 1;

    if(OK) return ;

    int b[5];

    for(int i = 0 ;i < 9 ;i ++)

    {

        if(t == 0 && i) break;

        int nowt = t + 1;

        int nowx = x + dir[i][0];

        int nowy = y + dir[i][1];

        for(int j = 1 ;j <= 4 ;j ++)

        b[j] = a[j] + 1;

        if(nowx == 1 && nowy == 1) b[1] = 0;

        if(nowx == 1 && nowy == 3) b[2] = 0;

        if(nowx == 3 && nowy == 1) b[3] = 0;

        if(nowx == 3 && nowy == 3) b[4] = 0;

        if(ok(nowt ,nowx ,nowy ,b))

        {

            mark[nowt][ys[(nowx-1)*4+nowy]][b[1]][b[2]][b[3]][b[4]] = 1;

            DFS(nowt ,nowx ,nowy ,b);

        }

    }

    return ;

}

int main ()

{

    int i ,j;

    while(~scanf("%d" ,&T) && T)

    {

        memset(DAY ,0 ,sizeof(DAY));

        for(i = 1 ;i <= T ;i ++)

        {

            int tmp;

            for(j = 1 ;j <= 16 ;j ++)

            {

                scanf("%d" ,&tmp);

                DAY[i] = DAY[i] | (tmp << j);

            }

        }

        memset(mark ,0 ,sizeof(mark));

        OK = 0;

        int a[5];

        a[1] = a[2] = a[3] = a[4] = 0;

        DFS(0 ,2 ,2 ,a);

        printf("%d\n" ,OK);

    }

    return 0;

}

POJ2044 深搜+剪枝(云彩下雨)的更多相关文章

  1. Hdu3812-Sea Sky(深搜+剪枝)

    Sea and Sky are the most favorite things of iSea, even when he was a small child.  Suzi once wrote: ...

  2. poj1190 生日蛋糕(深搜+剪枝)

    题目链接:poj1190 生日蛋糕 解题思路: 深搜,枚举:每一层可能的高度和半径 确定搜索范围:底层蛋糕的最大可能半径和最大可能高度 搜索顺序:从底层往上搭蛋糕,在同一层尝试时,半径和高度都是从大到 ...

  3. UVA 10160 Servicing Stations(深搜 + 剪枝)

    Problem D: Servicing stations A company offers personal computers for sale in N towns (3 <= N < ...

  4. ACM 海贼王之伟大航路(深搜剪枝)

    "我是要成为海贼王的男人!" 路飞他们伟大航路行程的起点是罗格镇,终点是拉夫德鲁(那里藏匿着"唯一的大秘宝"--ONE PIECE).而航程中间,则是各式各样的 ...

  5. hdu 1518 Square(深搜+剪枝)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1518 题目大意:根据题目所给的几条边,来判断是否能构成正方形,一个很好的深搜应用,注意剪枝,以防超时! ...

  6. POJ-1724 深搜剪枝

    这道题目如果数据很小的话.我们通过这个dfs就可以完成深搜: void dfs(int s) { if (s==N) { minLen=min(minLen,totalLen); return ; } ...

  7. 一本通例题-生日蛋糕——题解<超强深搜剪枝,从无限到有限>

    题目传送 显然是道深搜题.由于蛋糕上表面在最底层的半径确认后就确认了,所以搜索时的面积着重看侧面积. 找维度/搜索面临状态/对象:当前体积v,当前外表面面积s,各层的半径r[],各层的高度h[]. 可 ...

  8. 模拟赛T5 : domino ——深搜+剪枝+位运算优化

    这道题涉及的知识点有点多... 所以还是比较有意思的. domino 描述 迈克生日那天收到一张 N*N 的表格(1 ≤ N ≤ 2000),每个格子里有一个非 负整数(整数范围 0~1000),迈克 ...

  9. HDU 1175 连连看 (深搜+剪枝)

    题目链接 Problem Description "连连看"相信很多人都玩过.没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子.如果某两个相同的棋子,可以 ...

随机推荐

  1. 【转载】Java虚拟机类加载机制与案例分析

    出处:https://blog.csdn.net/u013256816/article/details/50829596 https://blog.csdn.net/u013256816/articl ...

  2. 【DB宝42】MySQL高可用架构MHA+ProxySQL实现读写分离和负载均衡

    目录 一.MHA+ProxySQL架构 二.快速搭建MHA环境 2.1 下载MHA镜像 2.2 编辑yml文件,创建MHA相关容器 2.3 安装docker-compose软件(若已安装,可忽略) 2 ...

  3. 使用SQLSERVER 2008 R2 配置邮件客户端发送DB数据流程要领

    设置邮件 QQ邮箱貌似不太行,建议用企业邮箱或者其他邮箱作为发件箱 新建一个邮件发件箱账号,具体邮件服务器按照各自邮件配置,是否使用ssl,自便 下一步,下一步,配置成功 use msdb Go DE ...

  4. 锐捷RG-UAC统一上网行为管理审计系统账号密码泄露漏洞 CNVD-2021-14536

    一:产品介绍: 锐捷 RG-UAC 统一上网行为管理审计系统 锐捷统一上网行为管理与审计RG-UAC系列是星网锐捷网络有限公司自主研发的上网行为管理与审计产品,以路由.透明.旁路或混合模式部署在网络的 ...

  5. 使用 .NET CLI 构建项目脚手架

    前言 在微服务场景中,开发人员分配到不同的小组,系统会拆分为很多个微服务,有一点是,每个项目都需要单元测试,接口文档,WebAPI接口等,创建新项目这些都是重复的工作,而且还要保证各个项目结构的大体一 ...

  6. MIMO OFDM 常用信号检测算法

    MIMO OFDM 系统检测算法 1. 前言 MIMO的空分复用技术可以使得系统在系统带宽和发射带宽不变的情况下容易地获得空间分集增益和信道的容量增益.OFDM技术采用多个正交的子载波并行传输数据,使 ...

  7. hive学习笔记之一:基本数据类型

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  8. POJ - 1163 The Triangle 【动态规划】

    一.题目 The Triangle 二.分析 动态规划入门题. 状态转移方程$$DP[i][j] = A[i][j] + max(DP[i-1][j], DP[i][j])$$ 三.AC代码 1 #i ...

  9. Python-sendgrid邮箱库的使用

    Python中sendgrid库使用 #帮助文档https://github.com/sendgrid/sendgrid-python https://sendgrid.com/docs/ui/acc ...

  10. 攻防世界 reverse easy_Maze

    easy_Maze 从题目可得知是简单的迷宫问题 int __cdecl main(int argc, const char **argv, const char **envp) { __int64 ...