zoukankan      html  css  js  c++  java
  • 【ZJOJ1321】灯

    题目

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

    分析

    发现,当我们打开一个开关,就会取反一些灯的状态:0/1;
    对于第i个开关,就可以有一个对其他灯是否有影响的n位的二进制数。
    一开始,所有灯的状态为0,
    现在要让他全部变为1,即(2^n-1)
    题目就转化为,n个二进制数,如何取最少的数使他们的异或中为(2^n-1)
    观察数据范围(nle35)
    直接枚举每个数选不选显然会超时。
    考虑,我们每次只枚举n/2个,
    先枚举前n/2个,将所有组合出的异或值扔进一个hash,或C++的map中(后者有点慢,为了方便,我打了map)
    再枚举剩下的,所有组合出的异或值与(2^n-1)异或一下,将异或出来的值看一下map中有没有,如果有,则与ans取min。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <map>
    const int maxlongint=2147483647;
    const int mo=1000000007;
    const long long N=45;
    using namespace std;
    int n,m,ans,tot;
    long long a[N],mi[N];
    map<long long,int> arr;
    void dg(int y,long long v,int dis)
    {
    	if(dis>ans) return;
    	if(v==mi[n]-1) ans=min(ans,dis);
    	else
    	{
    		if(arr[v]==0) arr[v]=dis;
    		else arr[v]=min(arr[v],dis);
    	}
    	if(y>n) return;
    	for(int i=y;i<=n;i++) dg(i+1,v^a[i],dis+1);
    }
    void dg1(int y,long long v,int dis)
    {
    	if(dis>ans) return;
    	if(v==mi[n]-1) ans=min(ans,dis);
    	else
    	{
    		tot++;
    		if(arr[(mi[n]-1)^v]!=0) ans=min(arr[(mi[n]-1)^v]+dis,ans);
    	}
    	if(y>n/2) return;
    	for(int i=y;i<=n/2;i++) dg1(i+1,v^a[i],dis+1);
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	mi[0]=1;
    	for(int i=1;i<=36;i++) mi[i]=mi[i-1]*2,a[i]=mi[i-1];
    	for(int i=1,x,y;i<=m;i++)
    	{
    		scanf("%d%d",&x,&y);
    		a[x]+=mi[y-1];
    		a[y]+=mi[x-1];
    	}
    	ans=maxlongint;
    	dg(n/2+1,0,0);
    	arr[0]=0;
    	dg1(1,0,0);
    	printf("%d",ans);
    }
    
  • 相关阅读:
    一行代码更改博客园皮肤
    fatal: refusing to merge unrelated histories
    使用 netcat 传输大文件
    linux 命令后台运行
    .net core 使用 Nlog 配置文件
    .net core 使用 Nlog 集成 exceptionless 配置文件
    Mysql不同字符串格式的连表查询
    Mongodb between 时间范围
    VS Code 使用 Debugger for Chrome 调试vue
    css权重说明
  • 原文地址:https://www.cnblogs.com/chen1352/p/9071429.html
Copyright © 2011-2022 走看看