UVa 10318 - Security Panel

来源:互联网 发布:淘宝嘉年华什么时候 编辑:程序博客网 时间:2024/05/17 23:17

题意:给你一种在3*3矩阵上的开关灯方式,求按哪几个开关能把r*c矩阵上的灯全部点亮

如果直接搜索,2^25再乘上对开关的操作肯定会超时,需要剪枝

剪枝方法:每走到第k行时,判断第k-2行是否全部点亮(第k行的操作不会影响到前k-2行),如果没有全部点亮,cut掉


#include <stdio.h>#include <string.h>int map[6][6],n,m,f;int vis[30];int ans[30];int dx[9]={-1,-1,-1,0,0,0,1,1,1};int dy[9]={-1,0,1,-1,0,1,-1,0,1};int cn[9];int dfs(int cur,int p[6][6]){    if(f)return 0;    if(cur==m*n)    {        int ct=0;        for(int i=0;i<n;i++)        {            for(int j=0;j<m;j++)            if(!p[i][j])ct++;        }        if(ct==0)        {for(int i=0;i<cur;i++)        ans[i]=vis[i];f=1;        }        return 0;    }    int x=cur/m;    int y=cur%m;    if(x>1&&!y)    {        int e=0;        for(int i=0;i<m;i++)        if(!p[x-2][i])e=1;        if(e)return 0;    }    vis[cur]=0;    dfs(cur+1,p);    vis[cur]=1;    int t[6][6];    memcpy(t,p,sizeof(t));    for(int i=0;i<9;i++)    {        int xx=x+dx[i];        int yy=y+dy[i];        if(cn[i])        {            if(xx>=0&&xx<n&&yy>=0&&yy<m)            {                t[xx][yy]=1-t[xx][yy];            }        }    }    dfs(cur+1,t);    return 0;}int main(){    char s[5];int u=0;    while(scanf("%d%d",&n,&m)==2)    {      if(!n&&!m)break;      memset(cn,0,sizeof(cn));      memset(map,0,sizeof(map));      memset(vis,0,sizeof(vis));      memset(ans,0,sizeof(ans));      for(int i=0;i<3;i++)      {          scanf("%s",s);          for(int j=0;j<3;j++)          {              if(s[j]=='*')cn[i*3+j]=1;          }      }      f=0;      dfs(0,map);      printf("Case #%d\n",++u);      int k=0;      if(!f)printf("Impossible.\n");      else      {for(int i=0;i<n*m;i++)      {          if(ans[i])          {              if(k)printf(" ");              printf("%d",i+1);k=1;          }      }      printf("\n");      }    }    return 0;}