zoukankan      html  css  js  c++  java
  • 【bzoj1770/Usaco2009 Nov】lights 燈——折半搜索

    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

    輸入細節:

    一共有五盞燈。燈1、燈4和燈5都連接著燈2和燈3。

    Sample Output

    3
    輸出細節:
    按下在燈1、燈4和燈5上面的開關。
     

    听说是高斯消元?不会写,留坑待填......
    写了折半,大概就是先搜前一半点的状态即其代价,f[i]表示状态i的最小代价;
    搜索后一半点的时候代价就是当前状态加上状态补集的代价。
    再加个hash判重就可以啦。
    代码:
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 typedef long long LL;
     5 const int N=36,mod=9875321;
     6 using std::min;
     7 int n,m,mni=0x3f3f3f3f,h;
     8 int hash[mod],tot=0,an[600000];
     9 struct node{int ne;LL to;}e[600000];
    10 LL all;
    11 int read(){
    12     int ans=0,f=1;char c=getchar();
    13     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    14     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
    15     return ans*f;
    16 }
    17 LL f[N];
    18 int Hash(LL x){
    19     int p=x%mod;
    20     for(int i=hash[p];i;i=e[i].ne)if(e[i].to==x)return i;
    21     e[++tot]=(node){hash[p],x};hash[p]=tot;
    22     return tot;
    23 }
    24 void dfs(int x,LL now,int st,int p){
    25     if(st>mni)return;
    26     if(x==h+1){
    27         LL no=now;no>>=1;
    28         if(no==all)mni=min(mni,st);
    29         if(!p){
    30             int k=Hash(no);
    31             if(an[k])an[k]=min(an[k],st);
    32             else an[k]=st;
    33         }
    34         else{
    35             int k=Hash(all-no);
    36             if(!an[k])return;
    37             mni=min(mni,st+an[k]);
    38         }
    39         return;
    40     }
    41     dfs(x+1,now,st,p);dfs(x+1,now^f[x],st+1,p);
    42 }
    43 int main(){
    44     n=read();m=read();all=(1LL<<n)-1;
    45     for(int i=1,a,b;i<=m;i++){
    46         a=read();b=read();f[a]|=(1LL<<b);f[b]|=(1LL<<a);
    47     }
    48     for(int i=1;i<=n;i++)f[i]|=(1LL<<i);
    49     h=n/2;dfs(1,0,0,0);h=n;dfs(n/2+1,0,0,1);
    50     printf("%d",mni);
    51     return 0;
    52 }
    53 
    bzoj1770
  • 相关阅读:
    Bootstrap(2)整体架构
    介绍 Microservice
    Websocket实例
    MYSQL-用户权限的验证过程(转)
    don't touch your phone in any unfamiliar way(转)
    你真的会玩SQL吗?Case的用法(转)
    android模拟器与PC的端口映射(转)
    Java Main如何被执行?(转)
    Linux crontab 命令格式与具体样例
    分享一个3D球面标签云
  • 原文地址:https://www.cnblogs.com/JKAI/p/7665368.html
Copyright © 2011-2022 走看看