• hdu4770:Lights Against Dudely(回溯 + 修剪)


    称号:hdu4770:Lights Against Dudely


    题目大意:相同是n*m的矩阵代表room,房间相同也有脆弱和牢固之分,如今要求要保护脆弱的房间。须要将每一个脆弱的房间都照亮,可是牢固的房间不同意照到灯。

    灯是成L形的,即在x,y上有一盏灯,那么(x - 1, y)和(x。 y + 1)就能够被照亮。当然包含(x。y)。题目又提供了一盏特殊的灯,它能够该改变方向。可是仅仅有一盏,能够用也能够不用。一个房间最多一盏灯。

    问要将这些脆弱的房间都照亮最少须要多少盏灯。


    解题思路:题目有说脆弱的房间最多15间,那么先枚举哪间脆弱的房间放特殊的灯,特殊的灯又须要枚举四个方向,之后的就都是普通的灯。

    复杂度(15 * 4 * 2^14)将近1000000,再加上仅仅要碰到一个房间它不能被照亮就返回,而且这里考虑到普通灯的形状。所以回溯的时候是从左下角開始往右上角方向走。这是为了在比較前面得到较小的灯数目。那么回溯中有个剪枝就能剪掉较早的剪掉不符合的情况。剪枝:假设到中间的灯的数量比最小的大或是相等。就能够直接返回。


    注意:这里灯的四个方向的坐标一定要细心,错在这找了一下午。还有中间不是有标记房间的状态:是否被照亮,这里回溯要改回原来的值这个地方也要小心。

    由于可能有的灯原先就是亮的。

    原先状态不一致。所以用tem数组做了记录。还有放在这个位置的灯若是照到了牢固的房间,或是已经放了灯的房间。这样的情况是不行的。可是灯能够照在边界上,这样的是能够的。感觉比較难的就是在回溯状态恢复这一块,一定要细心。


    代码:

    #include <stdio.h>
    #include <string.h>
    
    const int N = 205;
    const int INF = 0x3f3f3f3f;
    int n, m;
    char g[N][N];
    int visit[N][N]; //标记房间是否被照亮
    int mm;
    struct Tem {     //暂时数组存放回溯后要恢复的状态
    
    	int x, y, v;
    };
    
    const int dir[4][2][2] = {{{-1,0}, {0, 1}},  //特殊灯的四个方向
    	{{1, 0}, {0, 1}}, 
    	{{0, -1}, {1, 0}},
    	{{0, -1}, {-1, 0}}};
    
    int Min (const int x, const int y) { return x < y?

    x: y; } bool influence (int x, int y, int d, Tem * tem) { //d代表的是灯的方向 这个函数是用来处理这个位置的灯能影响到的房间。能够推断灯能不能放这个位置 tem[0].v = visit[x][y]; tem[0].x = x; tem[0].y = y; visit[x][y] = 1; int nx = x + dir[d][0][0]; int ny = y + dir[d][0][1]; if (nx >= 0 && nx < n && ny >= 0 && ny < m) { if (g[nx][ny] == '#') return false; else { tem[1].v = visit[nx][ny]; tem[1].x = nx; tem[1].y = ny; visit[nx][ny] = 1; } } int nx1 = x + dir[d][1][0]; int ny1 = y + dir[d][1][1]; if (nx1 >= 0 && nx1 < n && ny1 >= 0 && ny1 < m ) { if (g[nx1][ny1] == '#') return false; else { tem[2].v = visit[nx1][ny1]; tem[2].x = nx1; tem[2].y = ny1; visit[nx1][ny1] = 1; } } return true; } void undo (Tem * tem) { //回溯恢复visit状态 for (int i = 0; i < 3; i++) if (tem[i].v != -1) visit[tem[i].x][tem[i].y] = tem[i].v; } void dfs (int x, int y, int num) { //从左下角往右上角走 int newx, newy; if (x == -1) { mm = Min (mm, num); return; } newy = y + 1; newx = x; if (newy >= m) { newx = x - 1; newy = 0; } if (g[x][y] == '.') { // 推断脆弱的房间是否要放灯 bool flag = 0; if (visit[x][y]) { //已经被照亮的房间能够考虑不放灯 dfs(newx, newy, num); flag = 1; } if (num + 1 >= mm) //剪枝 大于等于最小值直接返回 return; Tem tem[3]; //放灯的情况 memset (tem, -1, sizeof (tem)); if (influence (x, y, 0, tem)) { g[x][y] = 'X'; dfs (newx, newy, num + 1); undo(tem); g[x][y] = '.'; } else { undo(tem); //不论能否够放都须要恢复状态,这个是由于我写的influence函数 if (!flag) //剪枝 这个房间不能被照亮直接返回 return; } } else dfs (newx, newy, num); } void solve () { //枚举特殊灯的位置。特殊灯的方向 mm = INF; memset (visit, 0, sizeof (visit)); bool flag = 1; Tem tem[3]; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) if (g[i][j] == '.') { flag = 0; g[i][j] = 'X'; for (int k = 0; k < 4; k++) { memset (tem, -1, sizeof (tem)); memset (visit, 0, sizeof (visit)); if (influence (i, j, k, tem)) dfs (n - 1, 0, 1); undo(tem); } g[i][j] = '.'; } if (mm == INF) { if (flag) printf ("0 "); else printf ("-1 "); } else printf ("%d ", mm); } int main () { while (scanf ("%d%d", &n, &m), n || m) { for (int i = 0; i < n; i++) scanf ("%s", g[i]); solve(); } return 0; }


    測试例子:

    2 2
    ##
    ##
    2 3 
    #.. 
    ..#
    3 3 
    ### 
    #.# 
    ###  
    4 2 
    #. 
    .. 
    .# 
    .. 
    1 1 

    2 1 


    1 2 
    #. 
    1 5 
    .#... 
    1 4 
    .#.. 
    2 5 
    ...#. 
    ####.  
    6 4 
    #.## 
    ..#. 
    #.#. 
    #..# 
    .... 
    ....  
    5 5 
    #..#. 
    ##.#. 
    ####. 
    #.### 
    #..##  
    2 2 
    .. 
    #. 
    2 2 
    .. 
    .. 
    2 2 
    ## 
    .# 
    2 2 
    ## 
    #.  
    2 3 
    ### 
    #.. 
    2 3 
    #.# 
    #.# 
    0 0


    输出:

    0
    2
    -1
    2
    1
    1
    1
    3
    2
    3
    7
    4
    1
    2
    1
    1
    1
    -1

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    odoo开发笔记 -- 后台代码什么时候需要注意编码格式
    mysql添加类似oracle的伪列及查看表信息
    windows10升级系统后,无法远程桌面连接服务器
    时间管理
    odoo开发笔记 -- odoo仪表板集成hightcharts
    odoo开发笔记 -- odoo10 视图界面根据字段状态,动态隐藏创建&编辑按钮
    odoo开发笔记 -- odoo源码下载地址(非官方)
    odoo开发笔记 -- 异常信息处理汇总
    macbook 安装oracle RAC
    ubuntu升级pip后, ImportError: cannot import name ‘main‘
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4723869.html
Copyright © 2020-2023  润新知