欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

算法第五章作业

程序员文章站 2024-03-01 18:23:40
...

1.你对回溯算法的理解

回溯算法就是一种有组织的系统最优化搜索技术,可以看作蛮力法穷举搜索的改进。它的实质就是在问题的解空间进行深度优先搜索。回溯法常常可以避免搜索所有可能的解,所以它适用于求解组织数量较大的问题。

回溯法的一般步骤:

      (1).针对所给问题,定义问题的解空间,它至少包含问题的一个(最优)解。

      (2).确定易于搜索的解空间结构,使得能用回溯法方便地搜索整个解空间。

      (3).以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索。

用回溯法求解问题时,常常遇到两种典型的解空间树:

  (1)子集树:但所有的问题是从n个元素的集合中找出满足某种性质的子集时,相应的解空间树成为子集树

  (2)排列树:当所给出问题是确定n个元素满足某种性质的排列时,相应的解空间称为排列树。          

剪枝函数(避免无效搜索):

      (1)用约束条件剪除得不到的可行解的子树

  (2)用目标函数剪取得不到的最优解的子树

回溯法的优点在于其结构明确,可读性强,易于理解,而且通过对问题的分析可以大大提高运行效率。

2.请说明“子集和”问题的解空间结构和约束函数

7-1 子集和问题 (50 分)

设集合S={x1,x2,…,xn}是一个正整数集合,c是一个正整数,子集和问题判定是否存在S的一个子集S1,使S1中的元素之和为c。试设计一个解子集和问题的回溯法。

输入格式:

输入数据第1行有2个正整数n和c,n表示S的大小,c是子集和的目标值。接下来的1行中,有n个正整数,表示集合S中的元素。 是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。

输出格式:

输出子集和问题的解,以空格分隔,最后一个输出的后面有空格。当问题无解时,输出“No Solution!”。

输入样例:

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

5 10
2 2 6 5 4

输出样例:

在这里给出相应的输出。例如:

2 2 6 

解空间结构:

算法第五章作业

约束函数:

用rest来表示从当前元素加到最后一个元素的总和,用来回溯时判断限界剪枝

当sum + rest >= c,即当前所选元素之和+从当前元素加到最后一个元素的总和>=目标值时,走右子树。

#代码

//
//  main.cpp
//  123
//
//  Created by 王子涵 on 2017/12/5.
//  Copyright © 2017年 王子涵. All rights reserved.
//

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//

#include<iostream>
using namespace std;
#define N 10000
int n, c, rest = 0;
int a[N];
int x[N] = {0};
int sum = 0;
bool backtrack(int t)
{
    if( sum == c )
        return true; 
    if( t > n )
        return false ;
    
    rest-=a[t];
    if(sum + a[t] <= c)
    {
        x[t] = 1 ;
        sum = sum+a[t] ;
        if ( backtrack(t+1) )
            return true;
        sum -= a[t];
    }
    if( sum + rest >= c) 
    {
        x[t] = 0 ;
        if ( backtrack(t+1) )
            return true;
    }
    rest += a[t];
    return false;
}
int main()
{
    cin >>n>>c;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        rest += a[i];
    }
    if (!backtrack(1)) cout << "No Solution!";
    else
        for( int i = 1; i <= n; i++)
            if ( x[i] )
                cout << a[i] << " ";
    cout << endl;
    return 0;
}

 

3.请说明在本章学习过程中遇到的问题及结对编程的情况

 本章学习过程中遇到的问题是如何构造解空间树以及进行剪枝,前者关乎解题思路,剪枝方法关乎效率。结对编程讨论加快了我们对解空间树的构造,同时也能很快的确定剪枝方法,加快了做题效率。