zoukankan      html  css  js  c++  java
  • ZOJ 1076 Gene Assembly(LIS+路径打印 贪心)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=76

    题目大意:在一个DNA上,给定许多基因的起始位置和结束位置,求出这条链上最多同时存在多少基因?并依次输出选择基因的序列号。

    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

    分析:有两种思路。1.最长上升子序列+路径打印;2.贪心

    法1:

     1 //dp[i] = max{0,dp[j]}+1,j<i
     2 //时间复杂度仍为 O(n^2)
     3 //
     4 
     5 # include<stdio.h>
     6 # include<string.h>
     7 # include<stdlib.h>
     8 # define MAX 1001
     9 
    10 struct node{
    11     int x,y,id;    //x,y分别是基因起始和结束位置,id表示基因的序列号
    12 }data[MAX];
    13 
    14 int n;
    15 int pre[MAX];    //记录前驱
    16 int dp[MAX];    //LIS中保存最大数目
    17 int output[MAX];    //记录输出
    18 
    19 int cmp(const void *a,const void *b){    //将序列从小到大排序
    20     struct node *c = (node *)a;
    21     struct node *d = (node *)b;
    22     if(c->x == d->x)
    23         return c->y - d->y;
    24     return c->x - d->x;
    25 }
    26 
    27 void solve(){
    28     int i,j,m;
    29     qsort(data,n,sizeof(data[0]),cmp);
    30     pre[0] = -1;
    31     dp[0] =1;
    32     for(i=1;i<n;i++){
    33         pre[i] = -1;
    34         dp[i] = 1;
    35         m = 0;
    36         for(j=0;j<i;j++){
    37             if(data[j].y < data[i].x){
    38                 if(m<dp[j]){
    39                     m = dp[j];        //LIS
    40                     pre[i] = j;
    41                 }
    42             }
    43         }
    44         dp[i] += m ;
    45     }
    46     j = m = 0;
    47     for(i=0;i<n;i++){    //找到最长的序列的最后一个
    48         if(dp[i] > m){
    49             j = i;
    50             m = dp[i];
    51         }
    52     }
    53     i = 0;
    54     while(j != -1){
    55         output[i++] = j;
    56         j = pre[j];
    57     }
    58     for(j=i-1; j>0; j--)
    59         printf("%d ",data[output[j]].id);
    60     printf("%d
    ",data[output[j]].id);
    61 }
    62 int main(){
    63     while(scanf("%d",&n) && n){      
    64         for(int i=0;i<n;i++){
    65             scanf("%d%d",&data[i].x,&data[i].y);
    66             data[i].id = i+1;
    67         }
    68         solve();
    69     }
    70     return 0;
    71 }

    法2:

     1 /*可以将基因起始点看成一个作业的开始时间,基因终点看成完成该作业的终止时间。用这些基因拼出长度最长的基因序列(连续的基因前一个终点不能大于等于后一个基因起始点),相当于求能完成的最多作业序列。这是贪心的典型例题。可用贪心算法解决,贪心策略——优先考虑先完成的作业。*/
     2 #include <stdio.h>
     3 #include <string.h>
     4 
     5 int input[1001][3];    //input[i][0]:起始位置,input[i][1]:终止位置,input[i][2]:编号
     6 
     7 int main( )
     8 {
     9     int N, i, j, k;
    10     int temp, max;
    11     /*输入基因个数N,N=0时测试结束*/
    12     while( scanf( "%d", &N ) )
    13     {
    14         if( N==0 )  break;    //输入结束
    15         memset( input, 0, sizeof(input) );
    16         /*输入基因起始点,终止点,并给基因编号*/
    17         for( i=0; i<N; i++ )
    18         {
    19             scanf( "%d%d", &input[i][0], &input[i][1] );
    20             input[i][2] = i + 1;
    21         }
    22         /*对基因按终止点小的排序,<1000的用例,选择排序法*/ 
    23         for( i=0; i<N; i++ )
    24         {
    25             temp = input[i][1];
    26             k = i;
    27             for( j = i + 1; j<N; j++ )
    28             {
    29                 if( temp>input[j][1] )
    30                 {
    31                     k = j;
    32                     temp = input[j][1]; 
    33                 }
    34             }
    35             temp = input[i][0];
    36             input[i][0] = input[k][0];
    37             input[k][0] = temp;
    38             temp = input[i][1];
    39             input[i][1] = input[k][1];
    40             input[k][1] = temp;
    41             temp = input[i][2];
    42             input[i][2] = input[k][2];
    43             input[k][2] = temp;
    44         }
    45         /*贪心选择输出被选择的基因编号*/
    46         max = input[0][1];
    47         printf( "%d", input[0][2] );
    48         for( i=1; i<N; i++ )
    49         {
    50             if( input[i][0]>max )
    51             {
    52                 printf( " %d", input[i][2] );
    53                 max = input[i][1];
    54             }
    55         }   
    56         printf("
    ");
    57     }
    58     return 0;
    59 }
  • 相关阅读:
    257. Binary Tree Paths
    324. Wiggle Sort II
    315. Count of Smaller Numbers After Self
    350. Intersection of Two Arrays II
    295. Find Median from Data Stream
    289. Game of Life
    287. Find the Duplicate Number
    279. Perfect Squares
    384. Shuffle an Array
    E
  • 原文地址:https://www.cnblogs.com/acm-bingzi/p/3234696.html
Copyright © 2011-2022 走看看