zoukankan      html  css  js  c++  java
  • The New Villa

    题目:The New Villa

    题目链接:http://poj.org/problem?id=1137

    题目大意:

      一个人买了一个别墅,里面有很多房间,特别的是这个别墅的房间里灯的开关是乱套的,也就是说房间1可能没有房间1的灯的开关,而有房间2和房间3的开关,现在从房间1出发,刚开始只有房间1是亮的,只能走到亮着的房间(还必须有门相通),现在问你走到房间n,并且只剩下房间n是亮着的步骤,如果有多个方法,输出步骤最少的。

    题目思路:

      啥也不说,n最大为10,暴力搜,注意剪枝就可以了。。。附上我的代码和代码解析,不过我的代码并不怎么给力,最后时间还是需要250。。。

      1 #include<stdio.h>
      2 #include<string.h>
      3 bool door[11][11];  //
      4 bool sw[11][11];    //如果i能控制j的灯,那么sw[i][j]=1
      5 int light;          //当前灯的状态,从0到1024
      6 int n;              //房间的总数量
      7 int count[11][11];  //某一扇门被经过的次数,可以用来控制递归次数,减少时间
      8 int num[11];        //记录房间开关的所有状态数量,达不到1024
      9 int nu[11][1024];   //记录每个房间开关的所有状态
     10 bool OK()           //判断是否只有卧室灯开着,结束判断为当前位置为卧室且OK()
     11 {
     12   if(light^(1<<(n-1))) return false;
     13   return true;
     14 }
     15 void Init()                 //初始化,处理每个房间开关可能的状态
     16 {
     17   for(int i=1;i<=n;i++)
     18   {
     19     for(int j=0;j<1024;j++)
     20     {
     21       if((1<<(i-1))&j) continue;  //不允许关掉自己房间的灯
     22       int o;
     23       for(o=1;o<11;o++)
     24       {
     25         if(sw[i][o]==1) continue;
     26         if((1<<(o-1))&j) break;   //如果没有该房间的控制权,不允许对其进行操作
     27       }
     28       if(o<11) continue;
     29       nu[i][num[i]++]=j;
     30     }
     31   }
     32 }
     33 void dis(int tmp)     //测试用。。。。
     34 {
     35   int co=0;
     36   while(tmp)
     37   {
     38     printf("%d ",tmp&1);
     39     tmp>>=1;
     40     co++;
     41   }
     42   co=11-co;
     43   while(co--)
     44   {
     45     printf("0 ");
     46   }
     47   printf("
    ");
     48 }
     49 
     50 int s[10000][2];         //保存当前的步骤情况
     51 int mint[10000][2],mino; //保存所有能成功的步骤中步骤最小的
     52 bool v[11][1024];        //保存是否遇到过这种情况,与下面的结合使用
     53 int vum[11][1024];       //vum[i][j]表示当前处在房间i,灯的状态为j,最小的步骤,剪枝用
     54 bool match;              //是否能完成任务
     55 void DFS(int i,int step)
     56 {
     57   if(v[i][light]&&step>=vum[i][light]) return ;
     58   //因为下面有个剪枝,通过0状态过去的和这个一样。不在这里刷新值是为了在下面的可以把step>=的都排除掉,更快。
     59   for(int j=0;j<num[i];j++)
     60   {
     61     int k=nu[i][j];        //可行的开关执行方案
     62     int tmp=light;         //保存原来的灯状态
     63     light^=k;              //操作开关
     64     int pre_step=step;     //保存原来的步骤
     65     for(int o=1;o<=n;o++)  //记录步骤
     66     {
     67       if((1<<(o-1))&k)
     68       {
     69         s[step++][0]=o;
     70       }
     71     }
     72     if(v[i][light]&&step>=vum[i][light])     //剪枝
     73     {
     74       light=tmp;
     75       step=pre_step;
     76       continue;
     77     }
     78     v[i][light]=1;
     79     vum[i][light]=step;
     80     if(i==n&&OK())          //如果完成操作
     81     {
     82       if(step<mino)
     83       {
     84         for(int o=0;o<step;o++)
     85         {
     86           mint[o][0]=s[o][0];
     87           mint[o][1]=s[o][1];
     88         }
     89         mino=step;
     90       }
     91       match=1;
     92       light=tmp;
     93       return ;
     94     }
     95     for(int j=1;j<=n;j++)
     96     {
     97       if(door[i][j]==1&&(light&(1<<(j-1))))  //如果有门相通
     98       {
     99         count[i][j]++;
    100         if(count[i][j]>n-1)
    101         {
    102           count[i][j]--;
    103           continue;
    104         }
    105         s[step][1]=j;
    106         DFS(j,step+1);      //进入下一个房间
    107         s[step][1]=-1;      //只在这里进行恢复,因为这里的恢复比恢复s[step][0]的快很多
    108         count[i][j]--;
    109       }
    110     }
    111     light=tmp;
    112     step=pre_step;
    113   }
    114 }
    115 void solve()          //展示步骤
    116 {
    117   int light=1;
    118   printf("The problem can be solved in %d steps:
    ",mino);
    119   for(int i=0;i<mino;i++)
    120   {
    121     if(mint[i][1]==-1)
    122     {
    123       if(light&(1<<(mint[i][0]-1)))
    124       {
    125         printf("- Switch off light in room %d.
    ",mint[i][0]);
    126       }
    127       else
    128       {
    129         printf("- Switch on light in room %d.
    ",mint[i][0]);
    130       }
    131       light^=(1<<(mint[i][0]-1));
    132     }
    133     else
    134     {
    135       printf("- Move to room %d.
    ",mint[i][1]);
    136     }
    137   }
    138 }
    139 int main()
    140 {
    141   int m,k,a,b,cas=1;
    142   while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    143   {
    144     if(n==0&&m==0&&k==0) break;
    145     memset(door,0,sizeof(door));
    146     for(int i=0;i<m;i++)
    147     {
    148       scanf("%d%d",&a,&b);
    149       door[a][b]=1;
    150       door[b][a]=1;
    151     }
    152     memset(sw,0,sizeof(sw));
    153     memset(num,0,sizeof(num));
    154     for(int i=0;i<k;i++)
    155     {
    156       scanf("%d%d",&a,&b);
    157       sw[a][b]=1;
    158     }
    159     Init();
    160     light=1;
    161     memset(s,-1,sizeof(s));
    162     mino=100000;
    163     match=0;
    164     memset(v,0,sizeof(v));
    165     DFS(1,0);
    166     printf("Villa #%d
    ",cas++);
    167     if(match==1)
    168     {
    169       solve();
    170       printf("
    ");
    171     }
    172     else printf("The problem cannot be solved.
    
    ");
    173   }
    174   return 0;
    175 }
  • 相关阅读:
    7月自动化测试公开课通知
    招高级自动化测试工程师
    招聘软件开发工程师/开发实习生
    Selenium关键字驱动测试框架Demo(Java版)
    Eclipse+Selenium自动化测试脚本设计V1.0
    WebDriver基本API使用(基于Java)V1.0
    测试体系建设 免费咨询服务
    UFTQTP 12 新特性
    招聘自动化测试工程师
    AppScan学习笔记
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5075150.html
Copyright © 2011-2022 走看看