• 算法设计与分析期末考试 on PTA


    4-1
    算法的复杂性有时间复杂性和空间复杂性之分。

    4-2
    若存在两个正的常数c和n0,对于任意n≥n0,都有T(n)≤c×f(n),则称T(n)= Ω (f(n))。

    4-3
    用贪心算法求解的问题一般具有两个重要性质是:
    贪心原则和最优子结构性质。

    4-4
    分支限界法采用
    深度
    优先的方式搜索解空间,回溯法采用
    广度
    优先的方式搜索解空间。

    4-5
    通常,
    贪心算法、分支限界、回溯的求解策略是自顶向下求解,
    动态规划是自底向上的递推求解。

    4-6
    回溯法搜索解空间树时,常用的两种剪枝函数为
    约束函数和限界函数

    4-7
    分支限界法主要有
    队列式 分支限界法和 优先队列式 分支限界法。
    5-1
    如下程序的功能是求解n后问题,请将程序补充完整。(每空2分,共10分)

    #include <iostream.h>
    #include <math.h>
    int n,count,*x;
    void Swap(int& a,int &b){
       int t=a;a=b;b=t; }
    bool Check(int i){    //检查当前第i个皇后的放法是否可行
       for (int k=1;k<i;k++)
           if (
    (a[i]==a[j])||(abs(a[i]-a[j])==i-j)
    )  return false;
        
    else return true
    ;
    }
    void Output(){
        //以表格的形式输出一个解(x1,x2,…,xn),皇后所在的行列位置为“Q”,其它位置输出“_”。
         count++;
         for ( int i=1;i<=n;i++){
             for (j=1;j<=n;j++)
               if (x[i]==j) cout<<" Q";
               else cout<<"_";
             cout<<endl;
         }
     }
    void Queen(int i){
        if  (i>n)Output();
        else 
            for (int j=i;j<=n;j++){
                
    x[i] = j
    ;
                if (check(i))  
    Queen(i+1)Swap(x[i],x[j]);
            }
    }
    void main(){
       cout<<endl<<"Please input n=";   cin>>n;  
       x=new int [n+1];
       for (int i=1;i<=n;i++) 
    x[i]=-1
    ;
       count=0;
       Queen(1);
       cout<<endl<<"Total ="<<count<<endl;
       delete[]x;
    }
    

    7-1 找第k小的数 (20分)
    设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数。

    提示:函数int partition(int a[],int left,int right)的功能是根据a[left]a[right]中的某个元素x(如a[left])对a[left]a[right]进行划分,划分后的x所在位置的左段全小于等于x,右段全大于等于x,同时利用x所在的位置还可以计算出x是这批数据按升非降序排列的第几个数。因此可以编制int find(int a[],int left,int right,int k)函数,通过调用partition函数获得划分点,判断划分点是否第k小,若不是,递归调用find函数继续在左段或右段查找。

    输入格式:
    输入有两行:

    第一行是n和k,0<k<=n<=10000

    第二行是n个整数

    输出格式:
    输出第k小的数

    输入样例:
    在这里给出一组输入。例如:

    10 4
    2 8 9 0 1 3 6 7 8 2
    输出样例:
    在这里给出相应的输出。例如:

    2

    //找第k小的数 
    #include <iostream> 
    using namespace std;   
    int partition(int a[], int left, int right) {
    //将数组a的第left到right个元素进行划分 	
        int x = a[left]; 	 	
        while (left < right){//采用快排策略 		
            while (left < right && a[right] >= x) right--; 	
            a[left] = a[right]; 		 		
            while (left < right && a[left] <= x) left++; 		
            a[right] = a[left]; 	
        } 	 	
    	a[left] = x; 	 	
    	return left; 
    }   
    int find(int a[], int left, int right, int k) {
    	//在数组a的第left到right中寻找第k小的数 	
    	int pos = partition(a, left, right);   	
    	if (k - 1 == pos) cout << a[k - 1]; 	
    	else if (k - 1 < pos)//判断下一次划分在哪一区间进行 
            find(a, left, pos - 1, k); 	
    	else find(a, pos + 1, right, k);   	
    	return 0;   
    }   
    int main() { 	
        int n, k; 	
    	cin >> n >> k;   	
    	int a[1000]; 	
    	for (int i = 0; i < n; i++) 		
            cin >> a[i];   	
        find(a, 0, n - 1, k);   	
        return 0;   
    }
    

    7-2 装箱问题 (10分)
    假设有N项物品,大小分别为s​1​​ 、s​2​​ 、…、s​i​​ 、…、s​N​​ ,其中s​i​​ 为满足1≤s​i​​ ≤100的整数。要把这些物品装入到容量为100的一批箱子(序号1-N)中。装箱方法是:对每项物品, 顺序扫描箱子,把该物品放入足以能够容下它的第一个箱子中。请写一个程序模拟这种装箱过程,并输出每个物品所在的箱子序号,以及放置全部物品所需的箱子数目。

    输入格式:
    输入第一行给出物品个数N(≤1000);第二行给出N个正整数s​i​​ (1≤s​i​​ ≤100,表示第i项物品的大小)。
    输出格式:
    按照输入顺序输出每个物品的大小及其所在的箱子序号,每个物品占1行,最后一行输出所需的箱子数目。

    输入样例:
    8
    60 70 80 90 30 40 10 20
    输出样例:
    60 1
    70 2
    80 3
    90 4
    30 1
    40 5
    10 1
    20 2
    5

    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main()
    {
        int n,top = 1,i,j,flag;
        int a[1001];
        int b[1001];
        scanf("%d",&n);
        for(i = 0;i < n;i++)
        {
            scanf("%d",&a[i]);
            b[i] = 100;
        }
        if(n == 1)
        {
            printf("%d %d
    %d
    ",a[0],top,top);
            return 0;
        }
        for(i = 0;i < n;i++)
        {
            flag = 0;
            for(j = 1;j <= top;j++)
            {
                if(b[j] >= a[i])
                {
                    b[j] -= a[i];
                    flag =1;
                    printf("%d %d
    ",a[i],j);
                    break;
                }
            }
            if(!flag)
            {
                top++;
                b[top] -= a[i];
                printf("%d %d
    ",a[i],top);
            }
        }
        printf("%d
    ",top);
        return 0;
    }
    

    7-3 0-1背包 (20分)
    给定n(n<=100)种物品和一个背包。物品i的重量是wi,价值为vi,背包的容量为C(C<=1000)。问:应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有两个选择:装入或不装入。不能将物品i装入多次,也不能只装入部分物品i。

    输入格式:
    共有n+1行输入: 第一行为n值和c值,表示n件物品和背包容量c; 接下来的n行,每行有两个数据,分别表示第i(1≤i≤n)件物品的重量和价值。

    输出格式:
    输出装入背包中物品的最大总价值。

    输入样例:
    在这里给出一组输入。例如:

    5 10
    2 6
    2 3
    6 5
    5 4
    4 6
    输出样例:
    在这里给出相应的输出。例如:

    15

    #include<iostream>
    using namespace std;
    int main(){
    	int n,c;
    	cin>>n>>c;
    	int w[105];
    	int v[105];
    	int dp[105][1005]={};
    	for(int i=1;cin>>w[i]>>v[i];i++);
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=c;j++){
    			dp[i][j]=dp[i-1][j];
    			if(j>=w[i])
    			dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
    		}
    	}
    	cout<<dp[n][c];
    } 
    

    8-1 算法复杂度分析题 (6分)
    请分别给出你求解7-1、7-2、7-3所设计算法的时空复杂度。
    时间复杂度都为O(n^2)
    8-2 算法应用题 (6分)
    采用启发式搜索A*算法求解以下八数码难题,其中(a)为初始状态,(b)为目标状态,给出求解思路及估价函数。
    在这里插入图片描述

    求解思路:
    对应网址
    用启发式搜索算法求解,A* 算法。
    定义六个结构体
    九宫格的各个数字,
    OPEN结点,
    OPEN表,
    CLOSED结点,
    CLOSED表,
    求解路径。
    自定义函数:
    初始化九宫格;
    判断两个九宫格是否一致;
    求某结点的hx值,即与目标结点九宫格不一样的元素个数;
    对OPEN表按照估价函数值的大小从小到大排序;
    判断某九宫格是否与OPEN表中某结点相同;
    判断某九宫格是否与CLOSED表中某结点相同;
    将一个九宫格中的数字全部复制到另一个九宫格中;
    求OPEN表中某结点的扩展结点;
    删除OPEN表中第一个结点;
    计算估价函数值并赋值;
    以矩阵形式打印九宫格;
    打印求解最终路径;
    启发式搜索函数寻找求解路径。

    估价函数:

    /*********先定义所需要的结构体*********/
    typedef struct{
    int num[3][3];       //九宫格数字
    }Squared;                //九宫格
    ​
    typedef struct{
    Squared stateself;   //九宫格
    int dx;              //结点在搜索树中的深度
    int hx;              //结点对应九宫格与目标九宫格不一样的元素个数
    int fx;              //估价函数fx=dx+hx
    }Open;                   //OPEN结点
    ​
    //求某结点的hx值,即与目标结点九宫格不一样的元素个数
    int GetHx(Squared a,Squared end){
      int count=0;
      for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
          if(a.num[i][j]!=end.num[i][j])
            count++;
        }
      }
      return count;
    }
    ​
    /**********计算估价函数值并赋值**********/
    void CalEvaluate(Open &op,Open pare,Squared end){
      op.dx=pare.dx+1;                 //求dx
      op.hx=GetHx(op.stateself,end);   //求hx
      op.fx=op.dx+op.hx;               //求fx
    }
    

    8-3 最长公共子序列问题(LCS) (16分)
    最长公共子序列问题(LCS) 下面的公式是最长公共序列子问题的递归关系式,Ci,j 表示序列Xi和Yj的最长公共子序列的长度,其中Xi={x1,x2,x3,…,xi},Yj={y1,y2,y3,…,yj}, bi,j 记录了Ci,j 的值是由哪一个子问题的解产生。
    在这里插入图片描述

    已知 X=(a, b, c ,b, d, a, b),Y=(b, d, c, a, b, a) (1)请根据以上动态规划方程给出C表和B表,下表为C表、B表参考格式,请通过上传文件、图片或者插入图片方式提交C表及B表;

    在这里插入图片描述
    在这里插入图片描述

    (2)根据表C和B的值,X与Y构成的最长公共子序列的长度为多少?
    最大长度为4
    (3)请给出X与Y构成的最长公共子序列?
    公共子序列为bcba

  • 相关阅读:
    Ubuntu16.04.1 安装Nginx
    Ubuntu16.04.1 安装Redis-Cluster
    SeekBar的简单使用
    Async异步处理
    SQLite
    Shareprefrence
    android中的主线程
    Fragment的简单使用
    ArrayAdapter的使用
    用Intent传递对数
  • 原文地址:https://www.cnblogs.com/SiriusZHT/p/14310776.html
Copyright © 2020-2023  润新知