zoukankan      html  css  js  c++  java
  • JZOJ1321 灯

    Description

      贝希和她的闺密们在她们的牛棚中玩游戏。但是天不从人愿,突然,牛棚的电源跳闸了,所有的灯都被关闭了。贝希是一个很胆小的女生,在伸手不见拇指的无尽的黑暗中,她感到惊恐,痛苦与绝望。她希望您能够帮帮她,把所有的灯都给重新开起来!她才能继续快乐地跟她的闺密们继续玩游戏!
      牛棚中一共有N(1 <= N <= 35)盏灯,编号为1到N。这些灯被置于一个非常复杂的网络之中。有M(1 <= M <= 595)条很神奇的无向边,每条边连接两盏灯。
      每盏灯上面都带有一个开关。当按下某一盏灯的开关的时候,这盏灯本身,还有所有有边连向这盏灯的灯的状态都会被改变。状态改变指的是:当一盏灯是开着的时候,这盏灯被关掉;当一盏灯是关着的时候,这盏灯被打开。
      问最少要按下多少个开关,才能把所有的灯都给重新打开。
      数据保证至少有一种按开关的方案,使得所有的灯都被重新打开。

    Input

      第一行:两个空格隔开的整数:N和M。

      第二到第M+1行:每一行有两个由空格隔开的整数,表示两盏灯被一条无向边连接在一起。没有一条边会出现两次。

    Output

      第一行:一个单独的整数,表示要把所有的灯都打开时,最少需要按下的开关的数目。

    Sample Input

    5 6
    1 2
    1 3
    4 2
    3 4
    2 5
    5 3

    Sample Output

    3

    Hint

    【样例说明】
      一共有五盏灯。灯1、灯4和灯5都连接着灯2和灯3。按下在灯1、灯4和灯5上面的开关。

    Solution

      这题也可以写高斯消元,这里是双向搜索。

      先dfs前半部分,用hash储存,再dfs后半部分。

      1 #include<cstdio>
      2 #define N 1000007
      3 using namespace std;
      4 int g[N],sum,mi,l,r,b[50][50],n,m;
      5 long long t[N],s[40],tt[40];
      6 bool e[50],f[50];
      7 int min(int x,int y)
      8 {
      9     if (x>y) return y;
     10     return x;
     11 }
     12 int hash(long long x)
     13 {
     14     int z=x%N;
     15     while (t[z]!=0&&t[z]!=x)
     16         z=(z+1)%N;
     17     return z;
     18 }
     19 int dfs(int x)
     20 {
     21     if (x>l)
     22     {
     23         int p=0;
     24         for (int i=1;i<=n;i++)
     25             f[i]=false;
     26         for (int i=1;i<=l;i++)
     27             if (e[i])
     28             {
     29                 f[i]=not f[i];
     30                 for (int j=1;j<=b[i][0];j++)
     31                     f[b[i][j]]=not f[b[i][j]];
     32                 p++;
     33             }
     34         long long num=0;
     35         for (int i=1;i<=n;i++)
     36             if (f[i]) num+=s[i];
     37         int k=hash(num);
     38         if (t[k]==0) g[k]=p;
     39         else g[k]=min(g[k],p);
     40         t[k]=num;
     41         return 0;
     42     }
     43     e[x]=true;
     44     dfs(x+1);
     45     e[x]=false;
     46     dfs(x+1);
     47 }
     48 int dfs1(int x)
     49 {
     50     if (x>r)
     51     {
     52         int p=0;
     53         for (int i=1;i<=n;i++)
     54             f[i]=false;
     55         for (int i=l+1;i<=n;i++)
     56             if (e[i])
     57             {
     58                 f[i]=not f[i];
     59                 for (int j=1;j<=b[i][0];j++)
     60                     f[b[i][j]]=not f[b[i][j]];
     61                 p++;
     62             }
     63         long long num=0;
     64         for (int i=1;i<=n;i++)
     65             if (f[i]) num+=s[i];
     66         int k=hash(s[n]*2-1-num);
     67         if (t[k]!=0)
     68             mi=min(p+g[k],mi);
     69         return 0;
     70     }
     71     e[l+x]=true;
     72     dfs1(x+1);
     73     e[l+x]=false;
     74     dfs1(x+1);
     75 }
     76 int ss(int x,int z)
     77 {
     78     if (z==0)
     79     {
     80         if (x<mi)
     81             mi=x;
     82         return 0;
     83     }
     84     if (x>=mi||x>3)
     85         return 0;
     86     for (int i=1;i<=n;i++)
     87         if (tt[i])
     88         {
     89             tt[i]=false;
     90             int zz=z;
     91             if (f[i])
     92                 zz++;
     93             else zz--;
     94             f[i]=not f[i];
     95             for (int j=1;j<=b[i][0];j++)
     96             {
     97                 if (f[b[i][j]])
     98                     zz++;
     99                 else zz--;
    100                 f[b[i][j]]=not f[b[i][j]];
    101             }
    102             ss(x+1,zz);
    103             f[i]=not f[i];
    104             for (int j=1;j<=b[i][0];j++)
    105                 f[b[i][j]]=not f[b[i][j]];
    106             tt[i]=true;
    107         }
    108 }
    109 int main()
    110 {
    111     scanf("%d%d",&n,&m);
    112     for (int i=1;i<=m;i++)
    113     {
    114         int x,y;
    115         scanf("%d%d",&x,&y);
    116         b[x][++b[x][0]]=y;
    117         b[y][++b[y][0]]=x;
    118     }
    119     l=n/2,r=n-l;
    120     s[1]=1; 
    121     for (int i=1;i<=n;i++)
    122     {
    123         f[i]=false;
    124         tt[i]=true;
    125     }
    126     mi=0xffffff;
    127     ss(0,n);
    128     for (int i=2;i<=n;i++)
    129         s[i]=s[i-1]*2;
    130     if (mi!=0)
    131     {
    132         dfs(1);
    133         dfs1(1);
    134     }
    135     printf("%d",mi);
    136 }
    View Code
  • 相关阅读:
    函数式编程
    go语言中strings包常用方法
    Go--实现两个大数相乘
    谷歌插件
    函数的防抖---js
    函数截流---js
    函数的记忆----函数性能优化
    word-break、word-wrap、white-space区别
    overflow属性
    利用边框写一个三角形
  • 原文地址:https://www.cnblogs.com/Tokisaki-Kurumi/p/9532884.html
Copyright © 2011-2022 走看看