• 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 }
  • 相关阅读:
    奉上简单的.Net后端开发模板
    C#之委托如此简单
    cordova环境搭建
    Linux实现免密码登录
    RHEL7网络管理NetworkManager和nmcli指令
    RHEL7中配置本地YUM软件源
    RHEL7 网口绑定Network Teaming
    Linux工具之top
    Linux工具之ss
    linux工具之lsof
  • 原文地址:https://www.cnblogs.com/acm-bingzi/p/3234696.html
Copyright © 2020-2023  润新知