部分和问题

来源:互联网 发布:新闻文章网站源码 编辑:程序博客网 时间:2024/05/16 06:00

最近重操旧业开始攻基本的算法~第一个算法:部分和问题,语言,C++

问题描述:给定整数a1,a2,a3....an,判断是否可以选出若干个数,使他们的和恰好为K。

输入:n=4,a={1,2,4,7}.k=13

输出: yes (13=2+4+7)


原理:使用递归解决,类似于剪枝,只要该方向的sum值加起来比k大,就立刻弃掉该分支,如果小,则继续伸枝。

源代码:

#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
using namespace std;
vector<int> a;
int k;
int flag = 0;
void function(int index, int sum, vector<int> record)
{
 if (index == a.size())
 {
  if (sum != k)
   return ;
 }
 if (sum > k)
 {
  return;
 }
 if (sum<k)
 {
  record[index] = 1;
  function(index + 1, sum + a[index],record);
  record[index] = 0;
  function(index+1,sum,record);
 }
 if (sum == k)
 {
  if (flag == 0)  //只打印一个yes
  {
   cout << "yes";
   flag = 1;
  }
  
  vector<int> tmp;
  for (int i = 0; i < record.size();i++)
  {
   if (record[i] == 1)
    tmp.push_back(a[i]);
  }
  cout  << " ("<<k<<"=";
  for (int i = 0; i < tmp.size(); i++)
  {
   if (i == tmp.size() - 1)
    cout << tmp[i];
   else
    cout << tmp[i] << "+";
  }
  cout << ")";
  return;
 }
}
int main(void)
{
int n;
cout << "n=";
cin >> n;
getchar();
for (int i = 0; i < n; i++)
{
 int tmp;
 cin >> tmp;
 a.push_back(tmp);
 getchar();
}
cin >> k;
vector<int> record = a;  //record用来记录该值是否被加入
for (int i = 0; i < record.size(); i++)
 record[i] = 0;
//对于每一个元素,都只有两种情况,取还是不取(当然这里考虑的是不能重复)将复杂的问题简单化
function(0, 0,record);
if (flag == 0)
    cout << "NO" << endl;
return 0;
}

效果:

可以解决多种答案情况,分析一下,对每个值都进行了取与不取的选择,时间效率个跟内存使用情况都比较大,不是很理想。

以下还有一种代码比较少的:

bool dfs(int index,int sum)

{
   if (i==n) return sum==k;

 if(dfs(index+1,sum)) return true;   //加上当前值的情况

if(dfs(index+1,sum+a[index])) return true;  //不加上当前index的情况

return false;   //如果前面都没有返回则返回false

}

这种比较简单,代码量少,时间空间的使用是一样的,这种也是提供了一种思路,用机器的思维去解决任务。

0 0
原创粉丝点击