算法设计与分析第5章作业回溯法

给定一组包含n个元素的正整数,从这组整数中选择若干个,使它们的和恰好为指定的数k,要求找出选择元素个数最少的解。若存在多个子集的和均为k,且元素个数相同而且最少,则全部输出这些子集或者任意输出一个子集均可。若无解,则输出“No solution”。

【输入形式】

第一行有两个整数,一个是元素个数,另一个是k的值。

第二行是n个整数。
【输出形式】

第一行表示选择的元素,元素之间以空格隔开。

第二行表示所选择的元素个数。
【样例输入1】

5 9

1 2 3 4 5
【样例输出1】

4 5

2

#include <iostream>
#include <list>
#include <stdio.h>
using namespace std;
 
//list<int> numList;   //相当于双向链表
int minCount = -1,arry=-1;
int ss[100][100];
void find_seq(int sum, int index, int * value, list<int> & seq)
{   
    static int count = 0;
    int temp;
    if(sum <= 0 || index < 0) {
       return; 
    }
    
    if(sum == value[index])
    {
        int n = 1;  if (n==1) count++;
        ss[count][n] = value[index];
//        printf("ss[%d][%d]= %d ",count,n, value[index]);
    //     printf("%d, value[index]);
        // 将迭代器iter初始化为指向 seq 容器的第一个元素 , end():最后一个元素的下一个位置
        for(list<int>::iterator iter = seq.begin(); iter != seq.end(); ++iter)
        {     
            n++; 
         //   printf("%d ", *iter);
//            printf("ss[%d][%d]= %d ",count,n, *iter);
           
            ss[count][n] = *iter;
            //ss[count][n] = *iter;
        }
        if(minCount == -1 || n < minCount)
        {
            minCount = n;
            arry = count;
        }
 //       printf("\t(一共%d个元素)\n",n);
        
    }
/*   push_back() 和push_front():使用list的成员函数push_back和push_front插入一个元素到list中。
 其中push_back()从list的末端插入,而 push_front()实现的从list的头部插入
    通过pop_back()删除最后一个元素,通过pop_front()删除第一个元素;序列必须不为空,
如果当list为空的时候调用pop_back()和pop_front()会使程序崩掉。
 
 */
    
    seq.push_back(value[index]); // push_back()从list的末端插入
    find_seq(sum-value[index], index-1, value, seq); //放value[index]
    seq.pop_back();  //删除最后一个元素

    find_seq(sum, index-1, value, seq); //不放value[index]
}
 
int main()
{
    int k,N;
    list<int> seq;
    cin >> N >> k;
    int value[N+1];

//    printf("正整数集合为::");
    for(int i = 0; i < N; ++i)
    {
       cin >> value[i];
    }  
//  printf("可能的序列如下:\n");
    find_seq(k, N-1, value, seq);
//  printf("第%d行的元素是最少的\n",arry);
   if(minCount != -1)
   {
       for(int i=1;i<=minCount;i++){
        cout <<ss[arry][i] << ' ';    
       }
       cout << endl;  
   }
   
   if(minCount == -1)
    {
      //  printf("没有能够相加为%d的组合\n",k);
      cout << "No solution" << endl;
    }
    else
    {
      //  printf("最少的组合元素为:%d,组合详情见上\n",minCount);
       cout << minCount << endl;
    }
    return 0;
}

根据要求,给出候选字符的所有组合形式。例如,给定字符集x={a,b,c,d},求所有的2个字符的组合形式,即:ab, ac, ad, bc, bd, cd。

【输入形式】

由console提供输入数据。第1行中有2个正整数n和m,分别表示候选字符集数组有n个字符,需要计算的组合的元素个数为m个。接下来的一行是X数组的元素,即候选集的字符。

【输出形式】

从console中读取输入,按字典序输出所有的组合形式。

【样例输入】

4 3

abcd

【样例输出】

abc

abd

acd

bcd

#include <cstring>
#include <iostream>

using namespace std;

void GetCombination(const char * chars, int n);

int main()
{   
    int N,K;
    cin >> N >> K;
    char a[N];
    cin>>a;
//    cout<<a<<endl;
    GetCombination(a, K);
    return 0;
}

void GetCombination(const char * chars, int n)
{
    int index[10];
    int strLength = strlen(chars);
    for (int i = 0; i < n;i++)
    {
        index[i] = i;
    }
    bool end = false;
    while(!end)
    {
        for(int i = 0; i < n; i++)
        {
            cout << chars[index[i]];
        }
        cout << endl;
        for(int i = n - 1; i >= -1; i--)
        {
            if(i < 0)
            {
                end = true;
                break;
            }
            if(index[i] < strLength - n + i)//strLength - 1 - ( n - 1 -i)
            {
                index[i]++;
                for(int j = i + 1; j < n ;j++)
                {
                    index[j] = index[j - 1] + 1;
                }
                break;
            }
        }
    }
}

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值