WHU 1548 Home 2-SAT
---恢复内容开始---
题意:
N个人想回家在至少一个时刻、至多两个时刻。并且,他们每个人都能独自回家。
定义:ai表示第i个人回家的时间, xij = abs(ai - aj) (i != j).
在每种时间计划中,定义 y = min{xij}。
问y最大可能是多少?
解法:
二分时间差的下界,用2-SAT判断是否可行。下确界即为所求。
代码:
这种是直接在跑的时候建边,是效率最快的
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int MAXN = ;
const int INF = (int)1e9+; int a[MAXN];
bool mark[MAXN];
int S[MAXN], c;
int n; inline int myAbs(int x) {
return x> ? x : -x;
} void init() {
memset(mark, false, sizeof(mark));
memset(S, , sizeof(S));
c = ;
} bool dfs(int u, int k) {
if (mark[u^]) return false; //如果他的对立面和他同时被标记,那么这种情况不应该发生
if (mark[u]) return true; //如果他已经被标记 mark[u] = true; //他被标记
S[c++] = u; //这个点入栈
for (int i = ; i < n*; i++) if (u!=i && (u^)!=i) {
if (myAbs(a[u^]-a[i])<k) {
if (!dfs(i, k)) return false;
}
}
return true;
} bool check(int k) {
init();
for (int i = ; i < n*; i += ) {
if (!mark[i] && !mark[i|]) { //如果这个点没有被标记
c = ;
if (!dfs(i, k)) { //如果x不能赋值为真
while (c>) mark[S[--c]] = false;
if (!dfs(i|, k)) return false; //如果x也不能赋值为假,那么无解
}
}
}
return true;
} void slove() {
int l = , r = INF, m;
while (l<r) {
m = (l+r)>>;
if (!check(m)) r = m;
else l = m+;
}
printf("%d\n", r-);
} int main() {
#ifdef Phantom01
freopen("WHU1548.in", "r", stdin);
#endif // Phantom01 while (scanf("%d", &n)!=EOF) {
int k;
for (int i = ; i < n; i++) {
scanf("%d %d", &k, &a[i<<]);
if (k&) a[i<<|] = a[i<<];
else scanf("%d", &a[i<<|]);
}
slove();
}
return ;
}
下面是先建边,再跑2-SAT
数组存邻接表(本地随机了20组数据,跑了12秒, oj跑了3秒)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector> using namespace std; const int MAXN = ;
const int INF = (int)1e9+; int Edge[MAXN], next[MAXN*MAXN], to[MAXN*MAXN], used;
int a[MAXN];
bool mark[MAXN];
int S[MAXN], c;
int n; inline int myAbs(int x) {
return x> ? x : -x;
} inline void addEdge(int u, int v) {
next[used] = Edge[u];
to[used] = v;
Edge[u] = used++;
} void init() {
memset(Edge, -, sizeof(Edge));
used = ;
memset(mark, false, sizeof(mark));
memset(S, , sizeof(S));
c = ;
} bool dfs(int u, int k) {
if (mark[u^]) return false; //如果他的对立面和他同时被标记,那么这种情况不应该发生
if (mark[u]) return true; //如果他已经被标记 mark[u] = true; //他被标记
S[c++] = u; //这个点入栈
for (int p = Edge[u]; p != -; p = next[p]) if (!dfs(to[p], k))
return false;
return true;
} bool check(int k) {
init(); for (int i = ; i < n*; i++) {
for (int j = ; j < i; j++) {
if (i==j || i==(j^)) continue;
if (myAbs(a[i]-a[j])<k) {
addEdge(i^, j);
addEdge(j^, i);
}
}
} for (int i = ; i < n*; i += ) {
if (!mark[i] && !mark[i|]) { //如果这个点没有被标记
c = ;
if (!dfs(i, k)) { //如果x不能赋值为真
while (c>) mark[S[--c]] = false;
if (!dfs(i|, k)) return false; //如果x也不能赋值为假,那么无解
}
}
}
return true;
} void slove() {
int l = , r = INF, m;
while (l<r) {
m = (l+r)>>;
if (!check(m)) r = m;
else l = m+;
}
printf("%d\n", r-);
} int main() {
#ifdef Phantom01
freopen("WHU1548.in", "r", stdin);
#endif // Phantom01 while (scanf("%d", &n)!=EOF) {
int k;
for (int i = ; i < n; i++) {
scanf("%d %d", &k, &a[i<<]);
if (k&) a[i<<|] = a[i<<];
else scanf("%d", &a[i<<|]);
}
slove();
}
return ;
}
下面是vector存边的(本地跑了30秒)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector> using namespace std; const int MAXN = ;
const int INF = (int)1e9+; vector<int> Edge[MAXN];
int a[MAXN];
bool mark[MAXN];
int S[MAXN], c;
int n; inline int myAbs(int x) {
return x> ? x : -x;
} void init() {
for (int i = ; i < n*; i++)
Edge[i].clear();
memset(mark, false, sizeof(mark));
memset(S, , sizeof(S));
c = ;
} bool dfs(int u, int k) {
if (mark[u^]) return false; //如果他的对立面和他同时被标记,那么这种情况不应该发生
if (mark[u]) return true; //如果他已经被标记 mark[u] = true; //他被标记
S[c++] = u; //这个点入栈
for (int i = ; i < Edge[u].size(); i++) if (!dfs(Edge[u][i], k))
return false;
return true;
} bool check(int k) {
init(); for (int i = ; i < n*; i++) {
for (int j = ; j < i; j++) {
if (i==j || i==(j^)) continue;
if (myAbs(a[i]-a[j])<k) {
Edge[i^].push_back(j);
Edge[j^].push_back(i);
}
}
} for (int i = ; i < n*; i += ) {
if (!mark[i] && !mark[i|]) { //如果这个点没有被标记
c = ;
if (!dfs(i, k)) { //如果x不能赋值为真
while (c>) mark[S[--c]] = false;
if (!dfs(i|, k)) return false; //如果x也不能赋值为假,那么无解
}
}
}
return true;
} void slove() {
int l = , r = INF, m;
while (l<r) {
m = (l+r)>>;
if (!check(m)) r = m;
else l = m+;
}
printf("%d\n", r-);
} int main() {
#ifdef Phantom01
freopen("WHU1548.in", "r", stdin);
#endif // Phantom01 while (scanf("%d", &n)!=EOF) {
int k;
for (int i = ; i < n; i++) {
scanf("%d %d", &k, &a[i<<]);
if (k&) a[i<<|] = a[i<<];
else scanf("%d", &a[i<<|]);
}
slove();
}
return ;
}
WHU 1548 Home 2-SAT的更多相关文章
- 多边形碰撞 -- SAT方法
检测凸多边形碰撞的一种简单的方法是SAT(Separating Axis Theorem),即分离轴定理. 原理:将多边形投影到一条向量上,看这两个多边形的投影是否重叠.如果不重叠,则认为这两个多边形 ...
- hdu 1548 楼梯 bfs或最短路 dijkstra
http://acm.hdu.edu.cn/showproblem.php?pid=1548 Online Judge Online Exercise Online Teaching Online C ...
- 三分 --- CSU 1548: Design road
Design road Problem's Link: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1548 Mean: 目的:从(0,0)到 ...
- POJ 1548 (二分图+最小路径覆盖)
题目链接:http://poj.org/problem?id=1548 题目大意:给出一张地图上的垃圾,以及一堆机器人.每个机器人可以从左->右,上->下.走完就废.问最少派出多少个机器人 ...
- hdu 1548 A strange lift
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1548 A strange lift Description There is a strange li ...
- hdu 1548 A strange lift 宽搜bfs+优先队列
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1548 There is a strange lift.The lift can stop can at ...
- HDU 1548 A strange lift (Dijkstra)
A strange lift http://acm.hdu.edu.cn/showproblem.php?pid=1548 Problem Description There is a strange ...
- whu 1464 deal with numbers
WHU 1464 deal with numbers 题意: 给你一串数字,对着串数字有三项操作: Minus a,b,c:对区间[a,b]总的每个数都减c. Division a,b,c:对区间[ ...
- POJ 3678 Katu Puzzle(2 - SAT) - from lanshui_Yang
Description Katu Puzzle is presented as a directed graph G(V, E) with each edge e(a, b) labeled by a ...
随机推荐
- SpringBoot学习笔记(10)-----SpringBoot中使用Redis/Mongodb和缓存Ehcache缓存和redis缓存
1. 使用Redis 在使用redis之前,首先要保证安装或有redis的服务器,接下就是引入redis依赖. pom.xml文件如下 <dependency> <groupId&g ...
- Dapper基础知识三
在下刚毕业工作,之前实习有用到Dapper?这几天新项目想用上Dapper,在下比较菜鸟,这块只是个人对Dapper的一种总结. Dapper,当项目在开发的时候,在没有必要使用依赖注入的时候,如何做 ...
- HTML提交表单
一.使用form提交表单 <form action="#" method="post"> {% csrf_token %} 班级<input ...
- NOIp2018模拟赛三十三
神奇的一场... 成绩:100+0+14=114 A题是个体面很恐怖的题...然而看懂题意之后转化一下就变成了一道暴力傻逼题...但是不知道为什么dalao们都没写,讲题的时候挺尴尬的...yrx“瞄 ...
- vue中使用viewerjs
项目创建 插件Viewer.js vue init webpack mytest001 安装viewerjs npm install viewerjs 删掉生成的项目里面的helloWord.vue ...
- 洛谷 P1373 小a和uim之大逃离 (差值型dp总结)
这道题和多米诺骨牌那道题很像 ,都是涉及到差值的问题. 这道题是二维的,同时要取模. 这种题,因为当前的决策有后效性,会影响到差值,所以直接把 差值作为维度,然后计算答案的时候把差值为0的加起来就行了 ...
- 一 Storm 基础
1 Storm 分布式计算结构称为 Topology (拓扑) Topology 由 stream(数据流).spout(数据流的生成者).bolt(运算)组成. ...
- Ubuntu 10.04 右上角网络管理图标消失的解决的方法
那个显示网络状态的那个图标.叫做:network-manager.假设是有线网络连接的话.是上下两个箭头,假设是无线网络的话.是一个发射信号的形状. sudo gedit /etc/Ne ...
- HDU 1022 Train Problem I 模拟栈题解
火车进站,模拟一个栈的操作,额外的栈操作,查看能否依照规定顺序出栈. 数据量非常少,故此题目非常easyAC. 直接使用数组模拟就好. #include <stdio.h> const i ...
- 1.Swift教程翻译系列——关于Swift
英文版PDF下载地址http://download.csdn.net/detail/tsingheng/7480427 我本来是做JAVA的.可是有一颗折腾的心,苹果公布Swift以后就下载了苹果的开 ...