一道暴力搜索的恶心剪枝题目。

先处理好某个点确定之后其他点的也确定的是谁,还有分别为什么情况,分别用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 (剪枝 + 状态压缩)的更多相关文章

  1. Sudoku (剪枝+状态压缩+预处理)

    [题目描述] In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. ...

  2. POJ2688状态压缩(可以+DFS剪枝)

    题意:       给你一个n*m的格子,然后给你一个起点,让你遍历所有的垃圾,就是终点不唯一,问你最小路径是多少? 思路:       水题,方法比较多,最省事的就是直接就一个BFS状态压缩暴搜就行 ...

  3. ACM/ICPC 之 BFS+状态压缩(POJ1324(ZOJ1361))

    求一条蛇到(1,1)的最短路长,题目不简单,状态较多,需要考虑状态压缩,ZOJ的数据似乎比POj弱一些 POJ1324(ZOJ1361)-Holedox Moving 题意:一条已知初始状态的蛇,求其 ...

  4. UVALive 3956 Key Task (bfs+状态压缩)

    Key Task 题目链接: http://acm.hust.edu.cn/vjudge/contest/129733#problem/D Description The Czech Technica ...

  5. HDOJ 1429 胜利大逃亡(续) (bfs+状态压缩)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 思路分析:题目要求找出最短的逃亡路径,但是与一般的问题不同,该问题增加了门与钥匙约束条件: 考虑 ...

  6. 状态压缩 - LeetCode #464 Can I Win

    动态规划是一种top-down求解模式,关键在于分解和求解子问题,然后根据子问题的解不断向上递推,得出最终解 因此dp涉及到保存每个计算过的子问题的解,这样当遇到同样的子问题时就不用继续向下求解而直接 ...

  7. uva10160(dfs+状态压缩)

    题意:给出n个点,以及m条边,这些边代表着这些点相连,修一个电力站,若在某一点修一个站,那么与这个点相连的点都可以通电,问所有的点都通电的话至少要修多少个电力站........ 思路:最多给出的是35 ...

  8. 状态压缩---UVA6625 - Diagrams & Tableaux

    比赛的时候刷出来的第一个状态DP.(期间有点没有把握是状态DP呢.) 题意:题意还是简单的.K行的方格.之后输入L1~LK 代表每一行方格数.在这些往左紧挨的方格子里填上1~N的数字. 其中右边格子的 ...

  9. dp状态压缩

    dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状 ...

随机推荐

  1. python_flask 注册,登陆,退出思路 ---纯个人观点

    1注册逻辑首先查询数据库用户名 并判断用户是否存在,如不存在就插入数据 并返回响应给前端2前端模板获取注册信息 判断 用户名不能为空及密码不能为空,和密码不一致 拼接注册url 组成get获取对象 响 ...

  2. 六、SpringBoot与数据访问

    六.SpringBoot与数据访问 1.JDBC spring: datasource: username: root password: 123456 url: jdbc:mysql://192.1 ...

  3. python练习题-day1

    1.使用while循环输入 1 2 3 4 5 6     8 9 10 count=0 while count<10: count+=1 if count==7: continue print ...

  4. mysql 初识sql语句

    有了mysql这个数据库软件,就可以将程序员从对数据的管理中解脱出来,专注于对程序逻辑的编写 mysql服务端软件即mysqld帮我们管理好文件夹以及文件,前提是作为使用者的我们,需要下载mysql的 ...

  5. dataframe操作

    1.去除重复项drop_duplication #去除重复项drop_duplication import pandas as pd df = pd.DataFrame({"col1&quo ...

  6. JsonResponse返回中文乱码问题

    class Publish(APIView): def get(self, request): publish_list = models.Publish.objects.all() bs = MyS ...

  7. [py]python __file__ 与argv[0]

    http://andylin02.iteye.com/blog/933237 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__ ...

  8. Java 基础 引用数据类型 和 流程控制

    引用数据类型 与定义基本数据类型变量不同,引用数据类型的变量定义及复制有一个相对固定的步骤和格式: 数据类型 变量名 = new 数据类型(); 如:String st = new String(); ...

  9. np.newaxis学习【转载】

    转自:https://blog.csdn.net/lanchunhui/article/details/49725065 1.相当于None >> type(np.newaxis) Non ...

  10. 笔记:yum和apt-get的区别

    rpm包和deb包是两种Linux系统下最常见的安装包格式,在安装一些软件或服务的时候免不了要和它们打交道. rpm包主要应用在RedHat系列包括 Fedora等发行版的Linux系统上, deb包 ...