您的位置:首页 > 其它

Codeforces 575C 状压+KM

2015-09-08 10:53 288 查看
题解链接:http://www.cygmasot.com/index.php/2015/09/08/codeforces_575c/

链接

题意:

给定n个人,把n个人分成周日上班和周六上班两批人。

一共有n个岗位。一个人对应一个岗位

第一个矩阵 i-th, j-th 意思是第i个人在周六上班 且任职第j个岗位的开心度。

第二个矩阵就是第i个人在周日上班 且任职第j个岗位的开心度。

求最大的开心度

思路:

枚举哪些人在第一批。然后KM。

=-=加个时限的黑科技。。
#include <map>
#include <iostream>  
#include <cstring>  
#include <string>  
#include <algorithm>  
#include <cstdio>  
#include <queue>
#include <cmath>
#include <set>
#include <stdio.h>
#include <ctime>  
 
using namespace std;
template <class T>
inline bool rd(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
template <class T>
inline void pt(T x) {
	if (x < 0) {
		putchar('-');
		x = -x;
	}
	if (x > 9) pt(x / 10);
	putchar(x % 10 + '0');
}
typedef pair<int, int> pii;
 
const int inf = 1e9;
const int N = 22;
const int M = N;
int ans;
struct KM {
	int n, w[M][M];
	int lx[M], ly[M], match[M], slack[M];
	bool s[M], t[M];
	inline bool hungary(int x) {
		s[x] = true;
		for (int y = 0; y < n; ++y)
			if (!t[y] && lx[x] + ly[y] == w[x][y]) {
				t[y] = true;
				if (match[y] == -1 || hungary(match[y])) {
					match[y] = x;
					return true;
				}
			}
			else slack[y] = min(slack[y], lx[x] + ly[y] - w[x][y]);
			return false;
	}
	inline int rediculous() {
		int magic;
		magic = 0;
		for (int i = 0; i < n; ++i) {
			lx[i] = *max_element(w[i], w[i] + n);
			magic += lx[i];
		}
		if (magic <= ans) return 0;
		memset(match, -1, n << 2);
		memset(ly, 0, n << 2);
		for (register int i = 0; i < n; ++i) {
			for (;;) {
				memset(s, 0, n);
				memset(t, 0, n);
				memset(slack, 0x7f, n << 2);
				if (hungary(i)) break;
				else {
					int a = inf;
					for (register int j = 0; j < n; ++j) if (!t[j] && slack[j] < a)
						a = slack[j];
					magic = 0;
					for (register int j = 0; j < n; ++j) {
						if (s[j]) lx[j] -= a;
						if (t[j]) ly[j] += a;
						magic += lx[j] + ly[j];
					}
					if (magic <= ans) {
						return 0;
					}
				}
			}
		}
		ans = magic;
		return magic;
	}
} S;
int n;
int a

, b

;
int CNT(int x) {
	int siz = 0;
	while (x) { siz += x & 1; x >>= 1; }
	return siz;
}
int main() {
	clock_t lim = clock() + 1.9*CLOCKS_PER_SEC;
	rd(n);
	S.n = n;
	for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)rd(a[i][j]);
	for (int i = 0; i < n; i++)for (int j = 0; j < n; j++) rd(b[i][j]);
	ans = 0;
	for (int i = 0; i < 1 << n; ++i)
		if (CNT(i) == (n >> 1))
		{
			for (int j = 0; j < n; j++)
				if (i&(1 << j))
					memcpy(S.w[j], a[j], n<<2);
				else
					memcpy(S.w[j], b[j], n<<2);
			ans = max(ans, S.rediculous());
			if (clock() >= lim)break;
		}
	pt(ans);
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: