ZOJ 1076 Gene Assembly(贪心 - 区间调度问题)

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1076

Statement of the Problem
  With the large amount of genomic DNA sequence data being made available, it is becoming more important to find genes (parts of the genomic DNA which are responsible for the synthesis of proteins) in these sequences. It is known that for eukaryotes (in contrast to prokaryotes) the process is more complicated, because of the presence of junk DNA that interrupts the coding region of genes in the genomic sequence. That is, a gene is composed by several pieces (called exons) of coding regions. It is known that the order of the exons is maintained in the protein synthesis process, but the number of exons and their lengths can be arbitrary.
  Most gene finding algorithms have two steps: in the first they search for possible exons; in the second they try to assemble a largest possible gene, by finding a chain with the largest possible number of exons. This chain must obey the order in which the exons appear in the genomic sequence. We say that exon i appears before exon j if the end of i precedes the beginning of j.
  The objective of this problem is, given a set of possible exons, to find the chain with the largest possible number of exons that cound be assembled to generate a gene.
Input Format
  Several input instances are given. Each instance begins with the number 0 < n < 1000 of possible exons in the sequence. Then, each of the next n lines contains a pair of integer numbers that represent the position in which the exon starts and ends in the genomic sequence. You can suppose that the genomic sequence has at most 50000 basis. The input ends with a line with a single 0.
Output Format
  For each input instance your program should print in one line the chain with the largest possible number of exons, by enumerating the exons in the chain. If there is more than one chain with the same number of exons, your program can print anyone of them.
Sample Input
6
340 500
220 470
100 300
880 943
525 556
612 776
3
705 773
124 337
453 665
0
Sample Output
3 1 5 6 4
2 3 1

区间调度问题:
  给你 n 个任务和每个任务的开始时间和结束时间,只有一台机器,这个机器一次只能完成一个任务。问这台机器最多能够完成多少任务?
区间调度问题解决方案:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int>P;
const int Max_n=1e5+10;
P a[Max_n];

int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            scanf("%d%d",&a[i].second,&a[i].first);
        sort(a,a+n);//按照结束时间排序(first)
        int j=0,num=0;
        for(int i=0;i<n;i++){
            if(j<=a[i].second){//结束时间<=开始时间不冲突
                j=a[i].first;//更新结束时间
                num++;
            }
        }
        printf("%d\n",num);
    }
    return 0;
}
  • 方案二:按照开始时间排序,当前任务不冲突,更新结束时间即可。当前任务冲突,我们需要判断当前任务的结束时间是不是更早一些,若是则需要更新最早结束时间。
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int>P;
const int Max_n=1e5+10;
P a[Max_n];

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            scanf("%d%d",&a[i].first,&a[i].second);
        sort(a,a+n);//按照开始排序
        int j=0,num=0;
        for(int i=0;i<n;i++){
            if(j<=a[i].first){//结束时间<=开始时间
                j=a[i].second;
                num++;
            }else if(a[i].second<j){//冲突但是当前的任务的结束时间较早
                j=a[i].second;
            }
        }
        printf("%d\n",num);
    }
    return 0;
}

  题意:给你一些基因组,并且给出开始位置和结束位置,求在不冲突的情况下,最多能找到多少个基因组,输出给出的基因组放在哪一个位置。
  思路:区间调度问题,对基因组按照右端点从大到小排序。每次选择右端点最小的基因组,在基因组进行弹出的时候记录他的位置即可。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int Max_n=1e3+10;
int ans[Max_n];

struct Node{
	int s,e,pos;
	bool operator <(const Node &a) const {
		return e>a.e;
	}
}node[Max_n];

bool cmp(Node a,Node b){
	if(a.e==b.e)
		return a.s<b.s;
	return a.e<b.e;	
}

priority_queue<Node>q;

int main(){
	int n;
	while(~scanf("%d",&n)&&n){
		for(int i=1;i<=n;i++){
			scanf("%d%d",&node[i].s,&node[i].e);
			node[i].pos=i;
		}
		sort(node+1,node+n+1,cmp);
		int cnt=0;
		for(int i=1;i<=n;i++){
			if(q.empty()){
				q.push(node[i]);
			} 
			if(q.top().e<node[i].s){
				ans[cnt++]=q.top().pos;
				q.pop();
				q.push(node[i]);
			}
		}
		while(!q.empty()){
			ans[cnt++]=q.top().pos;
			q.pop();
		}	
		for(int i=0;i<cnt;i++)
			printf("%d%c",ans[i],i==cnt-1?'\n':' ');	
	}
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值