【算法设计与分析】第一至六讲实验

1:

求最大公约数

【问题描述】求两个自然数m和n的最大公约数。

【评分标准】答案正确性及计算时间

#include<iostream>
using namespace std;
int CommFactor(int m, int n);

int main()
{
    int a, b, r;
    cin>>a>>b;
    r = CommFactor(a, b);
    cout<<r<<endl;
    return 0;
}
int CommFactor(int m, int n)
{
int r; 
	r = m % n;
	while(r!=0) 
	{
		m = n;
		n = r;
		r = m % n;
	}
    return n;
}

2:

n个重复数字求和问题

【问题描述】设计程序,该程序通过键盘输入获得整型数据a和n,计算sum=a+aa+aaa+...(共计n项),输出计算结果。

【输入形式】整形数据a和n,用空格隔开

【输出形式】求和结果

【样例输入】5 4

【样例输出】6170

【样例说明】如a=5,n=4,sum=5+55+555+5555

#include <cstdio>
 
//求和函数 
int getSum(int a,int n){
    int sum=0,last=a;
    for(int i=0;i<n;i++){
        sum+=a;
        //a+=a*10;
        a=a*10+last;//每次乘以10 加上末尾的数 
    }
    return sum;
}
 
int main(){
    int a,n;
    scanf("%d %d",&a,&n);
    int result=getSum(a,n);//调用求和函数 
    printf("%d",result);
    return 0;
}

求第k大的数

【问题描述】

求n个整数中第k大的数

【输入形式】

第一行输入n和k,第二行为n个整型数,都以空格分开

【输出形式】

第k大的数

【样例输入】

10 3

18 21 11 26 12 2 9 33 43 28

【样例输出】

28

【评分标准】

正确性与计算性能

#include <cstdio>
#include <malloc.h>
#include <search.h>
 
//快排cmp 
//int cmp(const void *a,const void *b){
//    return *(int*)a - *(int*)b;
//}
void QuickSort(int a[],int l,int r)
{
    int i,j,key;
    i=l;
    j=r;
    key=a[l];  //将第一个数作为基准数
    while(i<j)
    {
        while(i<j && key<=a[j])  //从数组后面开始,如果大于基准数,则跳过
        {
            j--;
        }
        if(i<j)     //找到第一个小于基准数的数,覆盖基准数的位置
        {
            a[i++]=a[j];
        }
        while(i<j && key>a[i])  //从数组前面开始,如果小于基准数,则跳过
        {
            i++;
        }
        if(i<j)     //找到第一个大于等于基准数的数,覆盖基准数的位置
        {
            a[j--]=a[i];
        }
    }
    a[i]=key;
    if(l<i-1)
    {
        QuickSort(a,l,i-1);
    }
    if(r>i+1)
    {
        QuickSort(a,i+1,r);
    }
}
 
int main(){
    int n,k;
    scanf("%d %d",&n,&k);
    int *ans=(int*)malloc(sizeof(int)*n);//定义一个数组空间ans 
    for(int i=0;i<n;i++){
        scanf("%d",&ans[i]);//依次存入数组 
    }
    
//    选择排序法 
//    for(int i=0;i<n;i++){
//        int minno=i;
//        for(int j=i+1;j<n;j++){
//            if(ans[j]<ans[minno]){
//                minno=j;
//            }
//        }
//        int temp=ans[minno];
//        ans[minno]=ans[i];
//        ans[i]=temp;
//    }
    
//    for(int i=0;i<n;i++){
//        printf("%d ",ans[i]);
//    }
//    printf("\n");
 
    QuickSort(ans,0,n-1);
    
    printf("%d",ans[n-k]);//打印结果 
    return 0;
}

 3:

整数排序

【问题描述】

从标准输入中输入一组互不相同的整数(个数不超过100)及排序方式,按照从小到大排序,输出按某种算法排序的结果及元素的比较次数。

【输入形式】

首先在屏幕上输入1个整数,表示待排序的整数个数,然后在下一行依次输入待排序的整数。各整数之间都以一个空格分隔。

【输出形式】

在一行上输出排序结果,各整数间以一个空格分隔。

【样例1输入】

10

46 65 -9 100 0 21 2 90 8 18

【样例1输出】

-9 0 2 8 18 21 46 65 90 100

【评分标准】

该题要求按照指定算法对输入的数据进行排序。程序语言可选C或C++。

#include <iostream>
#include <cstdio>
#include <malloc.h>
using namespace std;
 
int main(){
    //输入n和待排序数组 
    int n;
    cin>>n;
    int *input=(int*)malloc(sizeof(int)*n);
    for(int i=0;i<n;i++){
        cin>>input[i];
    }
    
    //选择排序
    for(int i=0;i<n-1;i++){
        int index=i;
        for(int j=i+1;j<n;j++){
            if(input[j]<input[index]){
                index=j;//record the min index
            }
        }
        //交换记录 
        if(index!=i){
            int t=input[i];
            input[i]=input[index];
            input[index]=t;
        }
    }
    
    //输出结果 
    for(int i=0;i<n;i++){
        if(i==n-1){
            cout<<input[i];//输出样式注意点 
        }
        else{
            cout<<input[i]<<" ";
        }
    }
    return 0;
}

最近点对

【问题描述】输入若干个二维点,横纵坐标分别依次存储于数组x, y中,请合理设计算法求出最近点对,并输出这个最近的距离。

【填写说明】

请阅读上下文并在空格处填入缺失代码。

最后距离的开方计算保留小数点后三位即可,提示:可采用二分查找实现。

【评分标准】结果正确的情况下结合计算时间排行获得相应分数。

#include<iostream>
using namespace std;
 
float ClosestPoints(float x[ ], float y[ ], int n);
int main()
{
    int n;
    float x[1000], y[1000];
 
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>x[i];
    }
    for(int i=0;i<n;i++)
    {
        cin>>y[i];
    }
    float min_distance = ClosestPoints(x, y, n);
    cout<<min_distance;
    return 0;
}
 
float ClosestPoints(float x[ ], float y[ ], int n)
{
//涓ゆ寰幆鎵炬渶灏忚窛绂?
    float d=(x[0]-x[1])*(x[0]-x[1])+(y[0]-y[1])*(y[0]-y[1]);
    for(int i=0;i<n-1;i++){
        for(int j=i+1;j<n;j++){
            if(d>(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])){
                d=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
            }
        }
    }
    
    float low,high,mid,e=0.0001;
    //distance<1 寮€鏂圭粨鏋滃湪0~1涔嬮棿 鍚﹀垯缁撴灉鍦?~d 
    if(d<1){
        low=d;
        high=1;
    }
    else{
        low=1;
        high=d;
    }
    
    //寮€鏂?
    while(high-low>e){
        mid=(high+low)/2;
        if(mid*mid>d){
            high=mid;
        }
        else{
            low=mid;
        }
    }
    
    mid*=1000;
    int ret=(int) mid;
    mid=(float)ret/1000;
    
    return mid;
}

 4:

分治法排序

选择一种本章分治法中介绍的算法,对整数数组进行排序。

#include <iostream>
#include <fstream>
using namespace std;
 
int length = 100000;
int arr[100000+1];
 
//start1
void swap(int *a,int *b){
    int *temp=a;
    a=b;
    b=temp;
}
 
void QuickSort(int a[],int start,int end){
    int newstart=start,newend=end;
    int mid=(start+end)/2;
    int temp=a[mid];
    //鍙湁涓€涓厓绱?or 涓婃鎺掑簭鍦ㄨ竟鐣?
    if(mid==end || start>end){
        return;
    }
    if(mid==start){
        if(a[start]>a[end]){
            swap(a[start],a[end]);
        }
        return;
    }
    while(end>start){
        while(a[start]<temp){
            start++;
        }
        while(end>=start && a[end]>=temp){
            end--;
        }
        if(end>start){
            swap(a[start],a[end]);
            if(mid==start){
                mid=end;
            }
        }
        else{
            swap(a[mid],a[start]);
            mid=start;
        }
    }
    QuickSort(a,newstart,mid-1);//宸︿晶鍫?
    QuickSort(a,mid+1,newend);//鍙充晶鍫?
}
//end1 
 
int main()
{
    ifstream inFile("array.dat", ios::in | ios::binary);
    if (!inFile) {
        cout << "error" << endl;
        return 0;
    }
    for (int i = 1; i <= length; i++)
    {
        inFile.read((char *)&arr[i], sizeof(int));
    }
    inFile.close();
 
//start2
QuickSort(arr,0,length);
//end2
 
    ofstream outFile("sorted.dat", ios::out | ios::binary);
    for (int i = 1; i <= length; i++)
    {            
        outFile.write((char*)&arr[i], sizeof(int));
    }
    outFile.close();
 
    return 0;
}

5:

减治法求解选择问题

设无序序列T =(r1, r2, …, rn),T 的第k(1≤k≤n)小元素定义为T按升序排列后在第k个位置上的元素。

给定序列T和整数k,寻找T的第k小元素的问题称为选择问题。

采用减治法设计一个高效的算法求解任意选择问题。

代码中数组下标从1开始,第0位置空缺。

#include <iostream>
#include <fstream>
using namespace std;
 
int length = 100000;
int arr[100000 + 1];
 
int Partition(int r[],int low,int high){
    int i=low,j=high;
    while(i<j){
        while(i<j&&r[i]<=r[j])
            j--;
        if(i<j){
            int temp=r[i];
            r[i]=r[j];
            r[j]=temp;
            i++;
        }
        while(i<j&&r[i]<=r[j])
            i++;
        if(i<j){
            int temp=r[i];
            r[i]=r[j];
            r[j]=temp;
        }
    }
    return i;
}
 
int SelectMinK(int r[],int low,int high,int k){
    int s;
    s=Partition(r,low,high);
    if(s==k)
        return r[s];
    if(s>k)
        return SelectMinK(r,low,s-1,k);
    else
        return SelectMinK(r,s+1,high,k);
}
 
int main()
{
    ifstream inFile("input.dat", ios::in | ios::binary);
    if (!inFile) {
        cout << "error" << endl;
        return 0;
    }
 
    int k = 0;
    inFile.read((char *)&k, sizeof(int));
 
    for (int i = 1; i <= length; i++)
    {
        inFile.read((char *)&arr[i], sizeof(int));
    }
    inFile.close();
 
    int v = 0; //Put the result in this variable.
    SelectMinK(arr,0,length,k);  
     v = arr[k];
    ofstream outFile("output.dat", ios::out | ios::binary);            
    outFile.write((char*)&v, sizeof(int));
    outFile.close();
 
    return 0;
}

6:

【问题描述】

给定一个序列,如果其中有些元素(也可能没有)被省略,则我们可以得到该序列的一个子序列。给定一个序列X = <x1...xn> ,另一个序列Z满足条件,存在严格递增索引序列I=<i1...ik>,使得对于所有j = 1,2,…,k, 有xij=zj,则称Z= <z1...zk>是X的子序列。

例如,Z = <a, b, f, c>是X = <a, b, c, f, b, c>的子序列。

给定两个序列X和Y,问题是求出X和Y的最大长度公共子序列的长度。

【输入形式】

两个给定字符串

【输出形式】

两个序列最大长度公共子序列的长度。

【样例输入】

abcfbc abfcab
【样例输出】

4

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
 
 
char str1[1000],str2[1000];
 
//定义取最大值函数 
int fmax(int a, int b) {
	if(a > b) return a;
	else return b;
}
 
//求公共子序列函数 
int longestCommonSubsequence(char* text1, char* text2) {
    int m = strlen(text1), n = strlen(text2);
    int dp[m + 1][n + 1];
    memset(dp, 0, sizeof(dp));
    for (int i = 1; i <= m; i++) {
        char c1 = text1[i - 1];
        for (int j = 1; j <= n; j++) {
            char c2 = text2[j - 1];
            if (c1 == c2) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            } 
			else {
                dp[i][j] = fmax(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }
    return dp[m][n];
}
 
//主函数 
int main(){
	scanf("%s %s",&str1,&str2);
	printf("%d",longestCommonSubsequence(str1,str2));
	return 0;
}

动态规划求最长递增子序列

 输出最长递增子序列的长度

#include  <iostream>
#include  <fstream>
using  namespace  std;
 
int length=100;
int arr[100];
 
int IncreaseOrder(int a[], int  n);
 
int main(){
    for(int i = 0; i < length; i++){
        cin >> arr[i];
    }
 
    int result = IncreaseOrder(arr, length);
 
    cout << result;
    return 0;
}
 
int inline fmax(int a,int b){
	return (a>b ? a : b);
}
 
#include <malloc.h>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
int IncreaseOrder(int a[],int n){
	int *dp=(int*)malloc(sizeof(int)*n),ret=0,max=0;
	memset(dp,0,sizeof(dp));
	dp[1]=1;
	for(int i=2;i<=n;i++){
		max=0;
		for(int j=1;j<i;j++){
			if(a[i-1]>a[j-1]){
				max=fmax(max,dp[j]);
			}
		}
		dp[i]=max+1;
		ret=fmax(ret,dp[i]);
	}
	return ret;
}
 
/*
int IncreaseOrder(int a[],int n){
	int dp[n+1];
    for(int i=0;i<=n;i++){
        dp[i] = 1;
    }
    int res=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<i;j++){
            if(a[i-1]>a[j-1]){
                dp[i]=fmax(dp[i],dp[j]+1);
                res=fmax(res,dp[i]);
            }
        }
    }
    return res;
}
*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MorleyOlsen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值