• POJ 3683 Priest John's Busiest Day(2-sat)


    POJ 3683 Priest John's Busiest Day

    题目链接

    题意:给定几个时间,si, ti, di每一个时间要选[si, si + di]或[ti - di, ti],问是否能选出全部时间不相交的方案

    思路:显然的2-sat,注意推断相交的方法

    代码:

    #include <cstdio>
    #include <cstring>
    #include <vector>
    using namespace std;
    
    const int N = 1005;
    
    
    int n;
    vector<int> g[2 * N];
    bool mark[2 * N];
    
    void init() {
    	memset(mark, false, sizeof(mark));
    	for (int i = 0; i < 2 * n; i++) g[i].clear();
    }
    
    void add_edge(int u, int x, int v, int y) {
    	g[(2 * u + x)^1].push_back(2 * v + y);
    	g[(2 * v + y)^1].push_back(2 * u + x);
    }
    
    int s[N], e[N], d[N];
    
    int S[2 * N], sn;
    
    bool dfs(int u) {
    	if (mark[u^1]) return false;
    	if (mark[u]) return true;
    	mark[u] = true;
    	S[sn++] = u;
    	for (int i = 0; i < g[u].size(); i++) {
    		int v = g[u][i];
    		if (!dfs(v)) return false;
    	}
    	return true;
    }
    
    bool judge(int s1, int e1, int s2, int e2) {
    	if (s1 >= s2 && s1 < e2) return true;
    	if (s2 >= s1 && s2 < e1) return true;
    	return false;
    }
    
    bool solve() {
    	init();
    	for (int i = 0; i < n; i++) {
    		for (int j = 0; j < i; j++) {
    			for (int x = 0; x < 2; x++) {
    				for (int y = 0; y < 2; y++) {
    					int s1, e1, s2, e2;
    					if (x == 0) {
    						s1 = s[i];
    						e1 = s[i] + d[i];
    					} else {
    						s1 = e[i] - d[i];
    						e1 = e[i];
    					}
    					if (y == 0) {
    						s2 = s[j];
    						e2 = s[j] + d[j];
    					} else {
    						s2 = e[j] - d[j];
    						e2 = e[j];
    					}
    					if (s1 > e1 || s2 > e2) return false;
    					if (judge(s1, e1, s2, e2))
    						add_edge(i, !x, j, !y);
    				}
    			}
    		}
    	}
    	for (int i = 0; i < n * 2; i += 2) {
    		if (!mark[i] && !mark[i + 1]) {
    			sn = 0;
    			if (!dfs(i + 1)) {
    				for (int j = 0; j < sn; j++) mark[S[j]] = false;
    				sn = 0;
    				if (!dfs(i)) return false;
    			}
    		}
    	}
    	return true;
    }
    
    int main() {
    	while (~scanf("%d", &n)) {
    		int h1, m1, h2, m2;
    		for (int i = 0; i < n; i++) {
    			scanf("%d:%d%d:%d%d", &h1, &m1, &h2, &m2, &d[i]);
    			s[i] = h1 * 60 + m1; e[i] = h2 * 60 + m2;
    		}
    		if (!solve()) printf("NO
    ");
    		else {
    			printf("YES
    ");
    			for (int i = 0; i < n; i++) {
    				int st, et;
    				if (mark[i * 2]) {
    					st = s[i];
    					et = s[i] + d[i];
    				} else {
    					st = e[i] - d[i];
    					et = e[i];
    				}
    				printf("%02d:%02d %02d:%02d
    ", st / 60, st % 60, et / 60, et % 60);
    			}
    		}
    	}
    	return 0;
    }


  • 相关阅读:
    解析ASP.NET WebForm和Mvc开发的区别
    relink:在Linux/UNIX平台上relink Oracle软件(转)
    Java开发 Eclipse使用技巧(转)
    职场人生:情商
    RPC
    PLSQL Developer Debug
    uC/OS-III学习2::uC/OS-III LED闪烁实验
    Flex文件读取报错
    C++字节对齐问题
    写可測试的代码
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8319865.html
Copyright © 2020-2023  润新知