hdu 4665 (dfs / 2-SAT)

题目链接


多校第六场的题目, 比赛时没什么想法, 后来看GYZ神犇的解题报告里用的是O(n ^ 2)的2 - SAT解法, 但本弱菜还是没想到如何构图, 后来看别人都是用dfs过的, 自己写了一版觉得还是挺好写的, 而且速度也很快, 但复杂度不知如何分析, 一开始觉得dfs应该会T的, 毕竟需要递归2000层, 后来想了想觉得这题有一定的特殊性, 因为题目只要求输出一组解, 而且如果相同同种颜色很多的话解的个数也会多, 所以dfs速度会比较快, 但准确的理论复杂度还是不知如何分析, 有时间再研究2-SAT解法吧。。。。。


#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <cctype>
#include <set>
#include <deque>
#include <map>

using namespace std;

inline int readint() {
	char c = getchar();
	while (!isdigit(c)) c = getchar();

	int x = 0;
	while (isdigit(c)) {
		x = x * 10 + c - '0';
		c = getchar();
	}

	return x;
}

int buf[10];

inline void writeint(int x) {
	int p = 0;
	if (x == 0) p++;
	else while (x) {
		buf[p++] = x % 10;
		x /= 10;
	}
	for (int j = p - 1; j >= 0; j--)
		putchar('0' + buf[j]);
}

const int N = 2005;
int cnt0[N], cnt1[N], sum[N];
int res[N], s0[N], s1[N], str[N];
int n;
bool ok = 0;

void dfs(int id, int sz0, int sz1) {
	if (id == n + 1) {
		for (int i = 1; i <= n; i++) 
			printf("%d", res[i]);
		puts("");	
		ok = 1;
		return;
	}

	if (cnt0[str[id]] < sum[str[id]] / 2 && (sz0 >= sz1 || str[id] == s1[sz0])) {
		res[id] = 0;
		cnt0[str[id]]++;
		s0[sz0] = str[id];
		dfs(id + 1, sz0 + 1, sz1);
		if (ok) return;
		cnt0[str[id]]--;
	}

	
	if (cnt1[str[id]] < sum[str[id]] / 2 && (sz1 >= sz0 || str[id] == s0[sz1])) {

		res[id] = 1;
		cnt1[str[id]]++;
		s1[sz1] = str[id];
		dfs(id + 1, sz0, sz1 + 1);	
		if (ok) return;
		cnt1[str[id]]--;
	}

}

int main() {
	int test;
	test = readint();
	while (test--) {
		n = readint();
		for (int i = 1; i <= n; i++)
			cnt0[i] = 0, cnt1[i] = 0, sum[i] = 0;

		for (int i = 1; i <= n; i++)
			str[i] = readint(), sum[str[i]]++;

		ok = 0;

		s0[1] = str[1];
		cnt0[str[1]]++;
		dfs(2, 2, 1);	
		
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值