POJ 1083

期间用了DP(可能更有些贪心的思想的算法),但是一个细节错误一直没有考虑

总体思路是这样的,按照每个区间的上界排序,然后从头到尾,定义\(dv(i)\)为前i个最少需要的并行数量

每次状态转移,从后向前搜索,每当发现当前区间\(i\)的下界比之前的区间的上界\(seg[j].e\)要小,说明二者必定重叠,直到遇到第一个不重叠的,把这第一个当作“父节点”,并更新父节点的上界。

这种思路大体是对的,但是有一个缺陷,就是随着父节点不断更新,最早加入的子节点有可能不知道父节点的上界会长大到什么程度,导致之后一些节点实际上已经不能加入他们所在组,但是因为只看子节点看不到这些局限,这样就漏掉了好多情况。

解决方案也显而易见,利用并查集

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
using namespace std;

const int maxn= 205;

struct Seg
{
	int s, e;
	Seg(int _s= 0, int _e= 0) : s(_s), e(_e) {}
	bool operator < (const Seg &rhs) const
	{
		return e< rhs.e;
	}
}segs[maxn];
int dv[maxn], fa[maxn];

inline void Init(int n)
{
	for (int i= 0; i< n; ++i){
		fa[i]= i;
	}
}
inline int Find(int x)
{
	if (x== fa[x]){
		return x;
	}
	return fa[x]= Find(fa[x]);
}
int main()
{
	int kase, n;
	int a, b;
	scanf("%d", &kase);

	while (kase--){
		scanf("%d", &n);
		for (int i= 0; i< n; ++i){
			scanf("%d %d", &a, &b);
			if (a> b){
				swap(a, b);
			}
			a= (a+1)>>1;
			b= (b+1)>>1;
			segs[i].s= a;
			segs[i].e= b;
		}
		Init(n);
		sort(segs, segs+n);

		dv[0]= 1;
		for (int i= 1; i< n; ++i){
			int flag= 1;
			for (int j= i-1; j>= 0; --j){
				int fa_j= Find(j);
				if (segs[i].s > segs[fa_j].e){
					segs[fa_j].e= segs[i].e;
					fa[i]= fa_j;
					flag= 0;
					break;
				}
			}
			dv[i]= flag ? dv[i-1]+1 : dv[i-1];
		}

		printf("%d\n", dv[n-1]*10);
	}
	return 0;
}

后面参考了别人的代码,发现另一种方法才更适合DP,完成之后记录如下

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
using namespace std;

const int maxn= 205;

int ov[maxn];

int main()
{
	int kase, n;
	int a, b;
	scanf("%d", &kase);

	while (kase--){
		scanf("%d", &n);
		memset(ov, 0, sizeof(ov));
		int ans= 0;
		for (int i= 0; i< n; ++i){
			scanf("%d %d", &a, &b);
			if (a> b){
				swap(a, b);
			}
			a= (a+1)>>1;
			b= (b+1)>>1;
			for (int i= a; i<= b; ++i){
				++ov[i];
				ans= max(ans, ov[i]);
			}
		}

		printf("%d\n", ans*10);
	}
	return 0;
}
posted @ 2021-04-21 20:02  IdiotNe  阅读(44)  评论(0编辑  收藏  举报