首页 > 代码库 > 【UVA】10318-Security Panel(DFS 回溯)

【UVA】10318-Security Panel(DFS 回溯)

比较纠结的一道题,改了好几次才对。

首先需要知道的就是每个点如果重复点2次是没有任何意义的,所以一个点只有选或者不选,那么时间复杂度最大为2^25

毫无疑问超过了允许的范围,那么考虑减枝。

由于是3 X 3 的改变范围,所以如果 当前走到了第三行,那么就没办法更改第一行的状态,如果走到了第四行就无法更改第一 二行的状态,所以如果这个时候第一 二行

还没改成亮的它永远也不可能亮了。

最后一个就是需要输出按开关的次数最小的方案,一开始没看见,WA了好几次。。

1417173510318Security PanelAcceptedC++0.0762014-09-09 11:49:25


#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,OK;
int mat[15];
const int dir[11][2] = {{-1,-1},{-1,0},{-1,1},{0,-1},{0,0},{0,1},{1,-1},{1,0},{1,1}};
int Map[30];
int rote[30],_rote[30];
bool Input(){
    scanf("%d%d",&n,&m);
    if(!n && !m) return false;
    for(int i = 0 ,k = 0; i < 3 ; i++){
        char str[10];
        scanf("%s",str);
        for(int j = 0 ; j < 3 ; j ++){
            if(str[j] == '.')
                mat[k++] = 0;
            else if(str[j] == '*')
                mat[k++] = 1;
        }
    }
    return true;
}
void DFS(int pos,int cur){/*位置,n行,m列,当前按了几个按钮*/
    int x = pos / m;
    int y = pos % m;
    if(pos == 3 * m){
        for(int i = 0 ; i < m ;i ++)
            if(Map[i] != 1)
                return ;
    }
    if(pos == 4 * m){  /*在第四行,前面2行的情况就固定了*/
        for(int i = 0 ; i < 2 * m; i++)
            if(Map[i] != 1)
                return ;
    }
    if(pos == m * n){
        for(int i = 0 ; i < pos ; i++)
            if(Map[i] != 1) return ;
        if(cur < OK){
            OK = cur;
            memcpy(_rote,rote,sizeof(rote));
        }
        return ;
    }
    /*是否对这个点进行更改,或者不更改*/
    rote[pos] = 0;
    DFS(pos + 1,cur);  /*不更改直接走下一个点*/
    /*对这个点进行更改*/
    for(int i = 0 ; i < 9 ; i++){
        int _x = x + dir[i][0];
        int _y = y + dir[i][1];
        if(_x >= 0 && _x < n && _y >= 0 && _y < m && mat[i]){
             int _pos = _x * m + _y;
             Map[_pos] = - Map[_pos];
        }
    }
    rote[pos] = 1;
    DFS(pos + 1,cur + 1);
    /*记得把状态改回去*/
    for(int i = 0 ; i < 9 ; i++){
        int _x = x + dir[i][0];
        int _y = y + dir[i][1];
        if(_x >= 0 && _x < n && _y >= 0 && _y < m && mat[i]){
             int _pos = _x * m + _y;
             Map[_pos] = - Map[_pos];
        }
    }
    return ;
}
int main(){
    int Case = 1;
    while(Input()){
        memset(Map,-1,sizeof(Map));
        memset(rote,0,sizeof(rote));
        OK = 100;
        DFS(0,0);
        printf("Case #%d\n",Case++);
        if(OK < 100){
            int k = 0;
            for(int i = 0 ; i < n * m ; i++){
                if(_rote[i]){
                    if(k) printf(" ");
                        printf("%d",i + 1);
                    k++;
                }
            }
            printf("\n");
        }
        else
            printf("Impossible.\n");
    }
    return 0;
}

【UVA】10318-Security Panel(DFS 回溯)