• 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
    ", 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
    ", ans*10);
    	}
    	return 0;
    }
    
  • 相关阅读:
    2017ICPC南宁补题
    H. The Game of Life
    I
    Twice Equation
    (贪心+队列)String
    Marcin and Training Camp
    莫比乌斯函数模版
    HDU-1695 莫比乌斯反演
    Steps to One DP+莫比乌斯反演
    Educational Codeforces Round 62 (Rated for Div. 2)
  • 原文地址:https://www.cnblogs.com/Idi0t-N3/p/14686717.html
Copyright © 2020-2023  润新知