黑马程序员--C语言算法十例(下)

----------------------ASP.Net+Unity开发.Net培训期待与您交流! ----------------------




六、最长公共子序列

描述

咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列。
tip
:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCSLongest Common Subsequence)。其定义是,一个序列S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。

输入

第一行给出一个整数N(0<N<100)表示待测数据组数
接下来每组数据两行,分别为待测的两组字符串。每个字符串长度不大于1000.

输出

每组测试数据输出一个整数,表示最长公共子序列长度。每组结果占一行。

样例输入

2

asdf

adfsd

123abc

abc123abc

样例输出

3

6

 

 

程序示例:

#include <stdio.h>
#include <string.h>
char s1[1001], s2[1001];
int dp[1001], t, old, tmp;
int main(){
   scanf("%d", &t);
   getchar();
   while(t--){
       gets(s1);
       gets(s2);
       memset(dp, 0, sizeof(dp));
       int lenS1=strlen(s1), lenS2=strlen(s2);
       for(int i=0; i<lenS1; i++){
           old=0;
           //若s1[i]==s2[j],dp[i][j] = dp[i-1][j-1]+1
           //否则,dp[i][j] =max(dp[i-1][j], dp[i][j-1])
           //此处进行了空间优化,old 代表 dp[i-1][j-1]
           //dp[j-1] 代表 dp[i][j-1],dp[j] 代表 dp[i-1][j]
           for(int j=0; j<lenS2; j++){
                tmp = dp[j];
                if(s1[i]==s2[j])
                    dp[j] = old+1;
                else
                   if(dp[j-1]>dp[j])dp[j]=dp[j-1];
                old = tmp;
           }
       }
       printf("%d\n", dp[lenS2-1]);
    }
   return 0;
}       
 

七、回文字符串

描述

所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如"aba"。当然,我们给你的问题不会再简单到判断一个字符串是不是回文字符串。现在要求你,给你一个字符串,可在任意位置添加字符,最少再添加几个字符,可以使这个字符串成为回文字符串。

输入

第一行给出整数N0<N<100
接下来的N行,每行一个字符串,每个字符串长度不超过1000.

输出

每行输出所需添加的最少字符数

样例输入

1

Ab3bd

样例输出

2

 

程序示例:

#include"stdio.h"
#include"string.h"
int a[1001][1001];
int main(){
       intT,i,j,len;
       chars[1001];
       scanf("%d",&T);
       while(T--){
              scanf("%s",s);
              len=strlen(s);
              memset(a,0,sizeof(a));
              for(i=1;i<=len;i++)
                     for(j=1;j<=len;j++){
                            if(s[i-1]==s[len-j])  a[i][j]=a[i-1][j-1]+1;
                            elseif(a[i-1][j]>a[i][j-1]) a[i][j]=a[i-1][j];
                            elsea[i][j]=a[i][j-1];
                     }
              printf("%d\n",len-a[len][len]);
       }
       return0;
}       


八、单调递增子序列(二)

描述

给定一整型数列{a1,a2...,an}0<n<=100000),找出单调递增最长子序列,并求出其长度。

如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5

输入

有多组测试数据(<=7
每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0<n<=100000)。
数据以EOF结束
输入数据保证合法(全为int型整数)!

输出

对于每组测试数据输出整形数列的最长递增子序列的长度,每个输出占一行。

样例输入

7

1 9 10 5 11 2 13

2

2 -1

样例输出

5

1

 

程序示例:

 

#include"stdio.h"
int a[100001];
int main(){
       inti,j,n,m,k;
       while(scanf("%d",&n)!=EOF){
              scanf("%d",&a[0]);
              k=0;
              for(i=1;i<n;i++){
                     scanf("%d",&m);
                     if(m<a[0]){
                            a[0]=m;
                     }elseif(m>a[k]){
                            a[++k]=m;
                     }else{
                            for(j=1;j<=k;j++){
                                   if(m<a[j]&&m>a[j-1]){
                                          a[j]=m;
                                          break;
                                   }elseif(m<a[j])
                                          break;
                            }
                     }
              }
              printf("%d\n",k+1);
       }
       return0;
}               

九、喷水装置(一)

描述

现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会让以它为中心的半径为实数Ri(0<Ri<15)的圆被湿润,这有充足的喷水装置i1<i<600)个,并且一定能把草坪全部湿润,你要做的是:选择尽量少的喷水装置,把整个草坪的全部湿润。

输入

第一行m表示有m组测试数据
每一组测试数据的第一行有一个整数数nn表示共有n个喷水装置,随后的一行,有n个实数riri表示该喷水装置能覆盖的圆的半径。

输出

输出所用装置的个数

样例输入

2

5

2 3.2 4 4.5 6

10

1 2 3 1 2 1.2 3 1.1 1 2

样例输出

2

5

 

程序示例:

 

#include"stdio.h"
#include"math.h"
#include"stdlib.h"
int main()
{
       inti,j,n,m,a,b,k,*q;
       doublet,sum,*p[10],s[600];
       scanf("%d",&n);
       q=(int*)malloc(sizeof(int)*n);
       for(i=0;i<n;i++){
              scanf("%d",&m);
       p[i]=(double*)malloc(sizeof(double)*m);
              for(j=0;j<m;j++)
                     scanf("%lf",s+j);
              p[i]=s;
              for(a=0;a<m-1;a++)
                     for(b=a+1;b<m;b++)
                            if(*(p[i]+a)<*(p[i]+b)){
                                   t=*(p[i]+a);
                                   *(p[i]+a)=*(p[i]+b);
                                   *(p[i]+b)=t;
                            }
              sum=0.0;
              for(k=0;k<m;k++){
                     if(sum<20)
                         sum+=2*sqrt(pow(*(p[i]+k),2)-1);
                     else
                            break;
              }
              q[i]=k;
       }
       for(i=0;i<n;i++)
              printf("%d\n",q[i]);
       return0;
}       

十、喷水装置(二)

描述

有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。

输入

第一行输入一个正整数N表示共有n次测试数据。
每一组测试数据的第一行有三个整数n,w,hn表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。
随后的n行,都有两个整数xiri,xi表示第i个喷水装置的的横坐标(最左边为0),ri表示该喷水装置能覆盖的圆的半径。

输出

每组测试数据输出一个正整数,表示共需要多少个喷水装置,每个输出单独占一行。
如果不存在一种能够把整个草坪湿润的方案,请输出0

样例输入

2

2 8 6

1 1

4 5

2 10 6

4 5

6 5

样例输出

1

2

 

程序示例:

 

#include"stdio.h"
#include"math.h"
#include"stdlib.h"
struct pen{
   int l;
   int r;
};
int main()
{
   struct pen a[10001];
       inti,j,k,count,T;
   int x,r,min,max,w,h,n,imax;
   scanf("%d",&T);
   while(T--){
       j=0;
       scanf("%d%d%d",&n,&w,&h);
       for(i=0;i<n;i++){
                     scanf("%d%d",&x,&r);
                     if(r>h/2.0){
                       a[j].l=x-sqrt(r*r-h/2.0*h/2.0);
                       if(a[j].l<0)
                            a[j].l=0;
                        a[j++].r=x+sqrt(r*r-h/2.0*h/2.0);
                        if(a[j-1].r>w)
                             a[j-1].r=w;
                     }
              }
              for(i=0;i<j-1;i++)
                     for(k=i+1;k<j;k++)
                            if(a[i].l>a[k].l){
                                   min=a[i].l;a[i].l=a[k].l; a[k].l=min;
                                   min=a[i].r;a[i].r=a[k].r; a[k].r=min;}
              count=0;
              if(a[0].l!=0||j==0)  count=0;
              elseif(a[0].r==w) count=1;
              else{
                     max=0;
                     for(i=0;i<j;i++){
                            imax=0;
                            for(k=i;k<j;k++){
                                   if(a[k].l<=max&&a[k].r>imax){
                                          imax=a[k].r;
                                   }
                                   if(a[k].l>max){
                                          i=k-1;break;
                                   }
                            }
                            max=imax;
                            if(max==0){
                                   count=0;
                                   break;
                            }
                            elseif(max==w){
                                   count++;break;
                            }
                            else{
                                   count++;
                            }
                     }
                     if(max!=w)
                            count=0;
              }
              printf("%d\n",count);
       }
       return0;
}        

 


----------------------ASP.Net+Unity开发.Net培训期待与您交流! ----------------------


详细请查看:www.itheima.com


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值