分类
标签
2-SAT AC自动机 BFS CDQ dfs DP fail树 FFT FFT&NTT FWT hash KD-Tree KMP LCA SPFA STL Tarjan Treap Trie 主席树 乱搞 二分 二分图匹配 二分答案 二维SPFA 交互 位运算 其他 最小生成树 分块 区间DP 半平面交 博弈论 可持久化 可持久化Trie树 后缀数组 图库 平衡树 并查集 插头DP 数学 数论 无旋Treap 日记 暴力 权值树状数组 栈 树DP 树套树 树状数组 树贪心 概率DP 模拟 欧拉定理 点分治 状压DP 生成函数 矩阵乘 线性规划 线段树 组合 网络流 群论 莫比乌斯反演 计算几何 贪心 费用流 高斯消元
814 字
4 分钟
BZOJ 1770 [Usaco2009 Nov]lights 燈 折半搜索
题目描述
贝希和她的闺密们在她们的牛棚中玩游戏。但是天不从人愿,突然,牛棚的电源跳闸了,所有的灯都被关闭了。贝希是一个很胆小的女生,在伸手不见拇指的无尽的黑暗中,她感到惊恐,痛苦与绝望。她希望您能够帮帮她,把所有的灯都给重新开起来!她才能继续快乐地跟她的闺密们继续玩游戏!
牛棚中一共有N(1 <= N <= 35)盏灯,编号为1到N。这些灯被置于一个非常复杂的网络之中。有M(1 <= M <= 595)条很神奇的无向边,每条边连接两盏灯。每盏灯上面都带有一个开关。当按下某一盏灯的开关的时候,这盏灯本身,还有所有有边连向这盏灯的灯的状态都会被改变。状态改变指的是:当一盏灯是开着的时候,这盏灯被关掉;当一盏灯是关着的时候,这盏灯被打开。问最少要按下多少个开关,才能把所有的灯都给重新打开。数据保证至少有一种按开关的方案,使得所有的灯都被重新打开。
输入
*第一行:两个空格隔开的整数:N和M。
*第二到第M+1行:每一行有两个由空格隔开的整数,表示两盏灯被一条无向边连接在一起。没有一条边会出现两次。
输出
第一行:一个单独的整数,表示要把所有的灯都打开时,最少需要按下的开关的数目。
样例输入
5 6
1 2
1 3
4 2
3 4
2 5
5 3
輸入細節:
一共有五盞燈。燈1、燈4和燈5都連接著燈2和燈3。
样例输出
3
輸出細節:
按下在燈1、燈4和燈5上面的開關。
题解
【折半搜索】
将需要搜索的元素分为不关联的两个部分,分别搜索
在本题中 N的范围有35如果直接搜的话会T的很惨
所以我们将N分为前后两部分
现将前mid个搜出来,记录每个状态集合的最小的答案
之后出来后mid + 1到n搜完后加上他的补集跟新答案
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
long long A[36], full, bin[37];
int Min = 0x3f, n, m;
map<long long, int> Mp;
void dfs1(int x, long long now, int k)
{
if(x == m + 1)
{
if(now == full)
Min = min(k, Min);
int t = Mp[now];
if(!t || t > k)
Mp[now] = k;
return;
}
dfs1(x + 1, now, k);
dfs1(x + 1, now^A[x], k + 1);
}
void dfs2(int x, long long now, int k)
{
if(x == n + 1)
{
if(now == full)
Min = min(k, Min);
int t = Mp[full - now];
if(!t)
return;
Min = min(t + k, Min);
return;
}
dfs2(x + 1, now, k);
dfs2(x + 1, now^A[x], k + 1);
}
int main()
{
// freopen("lights.in","r",stdin);
// freopen("lights.out","w",stdout);
int c;
scanf("%d%d", &n, &c);
bin[1] = 1;
for (int i = 2; i < 37; i++)
bin[i] = bin[i - 1] << 1;
int a, b;
for (int i = 1; i <= c; i++)
{
scanf("%d%d", &a, &b);
A[a] += bin[b];
A[b] += bin[a];
}
for (int i = 1; i <= n; i++)
A[i] += bin[i];
full = bin[n + 1] - 1;
m = n >> 1;
dfs1(1, 0, 0);
dfs2(m + 1, 0, 0);
printf("%d", Min);
}
BZOJ 1770 [Usaco2009 Nov]lights 燈 折半搜索
https://www.nekomio.com/posts/108/