Wooden Sticks

题目地址:

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19567

大概题意:

一个东西有两个属性值l和r,现在有一堆东西要使用他,分成几小堆使用,每小堆第一个使用需要1点消耗,但要求该小堆的后面使用的每一个东西的两个属性ll和rr都要比小于等于前一个(也就是ll<=l&&rr<=r),问你最少要花费多少点才能把所有东西都用完

这里用的是贪心,刚开始我很不理解这个正确性,后面想着想着就相同了(参考了这个人博客的样例http://blog.csdn.net/lishuhuakai/article/details/8117251)


上面所说的其实就是偏序关系,现在考虑一下贪心的正确性

定义A >= B为A.l>=B.l&&A.r>=B.r

如果这堆东西可以排成A>=B>=C...的顺序,那么答案很简单就是1,问题是会出现ABC..互相没有大小关系,通俗的说就是ABC不能互相包含的时候,那么三者肯定都各自需要一点消耗,那么以A为例,假如序列还存在a,b,c等被A包含着,那么a,b,c的关系又可能如ABC一样,那么关键问题来了A的下一个应该选谁?其实选谁都一样,因为这个点(例)a现在不选的,那么以后肯定要选a(BC顺便选a那是最好的情况,BC也遇到A的情形的话...循环想下去,最后肯定存在一个d点只能某D点选或者没有人选,没人选的话则必须花费一点消耗),...最后效果都一样

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <stack>
#include <map>
#include <queue>
#include <vector>

using namespace std;
const int maxn = 1e4+100;
const int INF = 0x3f3f3f3f;
#define pr(x)       cout << #x << " = " << x << " ";
#define prln(x)     cout << #x << " = " << x <<endl;
#define ll long long
struct Node{
	int l, r;
	bool operator < (const Node& rhs)const{
		return l > rhs.l || (l == rhs.l && r > rhs.r);
	}
}node[maxn];
bool vis[maxn];
int main(){
#ifdef LOCAL
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
  //freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
 #endif
    int n, t;
    scanf("%d", &t);
    while(t--) {
    	scanf("%d", &n);
    	for(int i = 0; i < n; ++i) {
    		scanf("%d%d", &node[i].l, &node[i].r);
    		vis[i] = 0;
    	}
    	sort(node, node+n);
    	int last = 0, num = INF, ans = 0, cnt = 0, st;
    	while(cnt < n) {
    		++ans;
    		num = INF;
    		st = last;
    		//prln(last);
    		last = 0;
    		for(int i = st; i < n; ++i) {
    			if(!vis[i]){
	    			if(num >= node[i].r) {
	    				num = node[i].r;
	    				++cnt;
	    				vis[i] = true;
	    			} else if(!last){
	    				last = i;
	    			}
    			}
    		}
		}    	
    	printf("%d\n", ans);
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值