Join The Future (剪枝 + 状态压缩)
一道暴力搜索的恶心剪枝题目。
先处理好某个点确定之后其他点的也确定的是谁,还有分别为什么情况,分别用vis,sta来记录。当然可以直接使用一个3进制数来表示,但是这里需要额外写一个三进制数求值的函数较为麻烦。然后写完就是搜索的问题了,搜索方向就是给点为0,1一直下去,如果没有剪枝,时间复杂度应该是O(240),显然TLE,题意给出的限制很大,我们依据它来剪枝就好了。然后就是求最小的字典序,其实只需要传进最上面那个数据就可以了,因为你已经确定了01情况,剩下的就是选择每个数的最小或者次小的数。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL; const int maxn = ;
const int mod = 1e9 + ;
const int inf = 0x3f3f3f3f;
vector<pair<int, int> >cnst[maxn];
int T,n,m,aa,bb,cc;
int l[maxn], r[maxn], trodi[maxn], vis[maxn];
LL b[maxn], odd[maxn][], cnt[maxn][], con[maxn], dans[maxn][], ans; ///求字典序最小的
void update(LL vis, LL sta){
LL pre = ;
bool better = false;
for(int i = ; i <= n; i ++){
int now;
if(vis & b[i]) now = l[i] + ((l[i] & ) != ((sta >> i & ) ^ pre));
else now = l[i];
if(better) trodi[i] = now;
else{
if(now > trodi[i]) return ;
if(now < trodi[i]) better = true, trodi[i] = now;
}
pre = pre ^ (now & );
}
} ///搜索所有01情况、剪枝、求总量
void dfs(int step, LL vis, LL sta){
if(step > n){
LL tmp = 0LL;
for(int i = ; i < ; i ++){
if((vis&b[n]) && (sta >> n & ) != i) continue;
tmp = (tmp + dans[n][i]) % mod;
}
if(tmp){
update(vis, sta);
ans = (ans + tmp) % mod;
}
return ;
}
dans[step][] = dans[step][] = ;
///(0, 1) * (0, 1) 的四种结果,求出当前节点为0,1的个数
for(int i = ; i < ; i ++){
if((vis&b[step]) && (sta >> step & ) != i) continue;
for(int j = ; j < ; j ++){
if((vis&b[step - ]) && (sta >>step - & ) != j) continue;
dans[step][i] = (dans[step][i] + dans[step - ][j] * cnt[step][i ^ j]% mod) % mod;
}
}
if(cnst[step].empty()) dfs(step + , vis, sta);
else
for(int i =; i < ; i ++) if(dans[step][i])
dfs(step + , vis | con[step], sta | odd[step][i]);
} void solve(){
///求出某个点确定了之后其他的限制情况,当某点确定之后奇偶情况其他点为奇数的点
for(int i = ; i <= n; i ++){
odd[i][] = odd[i][] = con[i] = ;
memset(vis, -, sizeof(vis));
queue<int>que;while(!que.empty())que.pop();
vis[i] = ;que.push(i);
while(!que.empty()){
int u = que.front();que.pop();
con[i] |= b[u];
odd[i][vis[u]] |= b[u];
for(auto x : cnst[u]){
int v = x.first, w = x.second;
if(~vis[v]){
if((vis[u] ^ vis[v] != w)){
printf("0\n-1\n");return ;
}
}else{
vis[v] = vis[u] ^ w;
que.push(v);
}
}
}
}
memset(trodi, inf, sizeof(trodi));
ans = 0LL; dans[][] = ;
dfs(, con[], odd[][]);
if(trodi[] == inf) printf("0\n-1\n");
else{
printf("%lld\n",ans);
for(int i = ; i <= n; i ++)
printf("%d%c", trodi[i], " \n"[i == n]);
}
} int main(){
scanf("%d",&T);
for(int i = ; i < maxn; i ++) b[i] = 1ll << i;
while(T --){
scanf("%d%d",&n,&m);
for(int i = ; i <= n; i ++){
scanf("%d%d", &l[i], &r[i]);
cnt[i][l[i]&] = (r[i] - l[i]) / + ;
cnt[i][(l[i]&)^] = r[i] - l[i] + - cnt[i][l[i]&];
}
for(int i = ; i <= n; i ++) cnst[i].clear();
for(int i = ; i < m; i ++){
scanf("%d%d%d",&aa, &bb, &cc);
cnst[aa - ].push_back(make_pair(bb, cc));
cnst[bb].push_back(make_pair(aa - , cc));
}
solve();
}
return ;
}
Join The Future (剪枝 + 状态压缩)的更多相关文章
- Sudoku (剪枝+状态压缩+预处理)
[题目描述] In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. ...
- POJ2688状态压缩(可以+DFS剪枝)
题意: 给你一个n*m的格子,然后给你一个起点,让你遍历所有的垃圾,就是终点不唯一,问你最小路径是多少? 思路: 水题,方法比较多,最省事的就是直接就一个BFS状态压缩暴搜就行 ...
- ACM/ICPC 之 BFS+状态压缩(POJ1324(ZOJ1361))
求一条蛇到(1,1)的最短路长,题目不简单,状态较多,需要考虑状态压缩,ZOJ的数据似乎比POj弱一些 POJ1324(ZOJ1361)-Holedox Moving 题意:一条已知初始状态的蛇,求其 ...
- UVALive 3956 Key Task (bfs+状态压缩)
Key Task 题目链接: http://acm.hust.edu.cn/vjudge/contest/129733#problem/D Description The Czech Technica ...
- HDOJ 1429 胜利大逃亡(续) (bfs+状态压缩)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 思路分析:题目要求找出最短的逃亡路径,但是与一般的问题不同,该问题增加了门与钥匙约束条件: 考虑 ...
- 状态压缩 - LeetCode #464 Can I Win
动态规划是一种top-down求解模式,关键在于分解和求解子问题,然后根据子问题的解不断向上递推,得出最终解 因此dp涉及到保存每个计算过的子问题的解,这样当遇到同样的子问题时就不用继续向下求解而直接 ...
- uva10160(dfs+状态压缩)
题意:给出n个点,以及m条边,这些边代表着这些点相连,修一个电力站,若在某一点修一个站,那么与这个点相连的点都可以通电,问所有的点都通电的话至少要修多少个电力站........ 思路:最多给出的是35 ...
- 状态压缩---UVA6625 - Diagrams & Tableaux
比赛的时候刷出来的第一个状态DP.(期间有点没有把握是状态DP呢.) 题意:题意还是简单的.K行的方格.之后输入L1~LK 代表每一行方格数.在这些往左紧挨的方格子里填上1~N的数字. 其中右边格子的 ...
- dp状态压缩
dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状 ...
随机推荐
- Glide加载图片报错You must not call setTag() on a view Glide is targeting
报错信息为:You must not call setTag() on a view Glide is targeting 原因就是View使用setTag后导致Glide之前请求的标记被清除,强制转 ...
- 实验四 Android程序设计
20155224 实验四 Android程序设计 实验报告 实验报告封面: 课程:Java程序设计 班级:1652班 姓名:王高源 学号:20165225 指导教师:娄嘉鹏 实验日期:2018年5月1 ...
- linux配置IP访问权限
允许访问vi /etc/hosts.allow添加(可以添加多行,其中“:allow”可以省率)sshd:192.168.81.*:allow #表示192.1 ...
- 重写toString()
重写Object的toString()之前,得到的结果是 类型 @ 内存地址 demo: package cn.sasa.demo1; public class Test { public stat ...
- POJ1845 sumdiv 数论
正解:小学数学数论 解题报告: 传送门! 其实不难但我数学这个方面太菜了所以还是多写点儿博客趴QAQ 然后因为是英文的所以先翻译一下,,,? 大概就是说求AB的所有约数之和,对9901取膜 这个只需要 ...
- spring mvc 资源映射配置
在springmvc配置文件中添加 <mvc:resources location="/css/" mapping="/css/**"/> < ...
- Springboot打包war
pom: 1.<packaging>war</packaging> 2.<dependency> <groupId>org.springframewor ...
- 006-UDP用户数据报文协议
一.概述 用户数据报协议(英语:User Datagram Protocol,缩写为UDP),又称用户数据报文协议,是一个简单的面向数据报的传输层协议,正式规范为RFC 768. 在TCP/IP模型中 ...
- chkdsk 命令对Raid盘检测和查错、修复
C:\Documents and Settings\Administrator>chkdsk /?检查磁盘并显示状态报告. CHKDSK [volume[[path]filename]]] [/ ...
- Z字形扫描
#include<cstdio> #include<iostream> #include<algorithm> #include<vector> #in ...