Метод на пълно изчерпване

Николай Киров

1. Задача за подмножества.

Даден е масив A с N елемента - естествени числа и цяло число S.  Да се намерят всички суми на елементи на масива, които са равни на S.

Вариант 1 - най-просто решение
#include <iostream>
#include <cmath>

int const N=4;
int const A[N]={1,2,3,4};
int const SUM = 6;

int two_p(int n)
{ return static_cast<int>(pow(2,n)); }

int const NN = two_p(N);

void count()
{
 int i, j;
 for(i=1; i<NN; i++)
 {
  int sum=0;
  for(j=0; j<N; j++) if (two_p(j) & i)
  {
   sum+=A[j]; cout << A[j] << "+";
  }
  if (sum==SUM) cout << "   OK";
  cout << endl;
 }
}

int main()
{
 count();
 cin.get();
 return 0;
}

Вариант 2:
Име на входния файл: SUM.INP

Описание на входния файл:
Първият ред на файла съдържа число - броя на примерите. Всеки пример започва с 2 числа - броя на елементите на масива N и търсената сума S. След това са дадени N естествени числа - елементите на месива.

Име на изходния файл: SUM.OUT

Описание на изходния файл:
За всеки пример на отделен ред се извеждат индексите на онези елементи на масива, чиято сума е точно S. Индексирането започва от 0 и индексите са наредени по възходящ ред. След всеки пример се оставя по един празен ред.

Примерен входен файл:
2
4 1
1 2 3 4
9 1
1 1 1 1 1 1 1 1 1

Изходен файл за примерния входен файл:
0 1 2
1 3

0 1 2 3 4 5 6 7 8
 

#include <fstream>
#include <cmath>
#define inttype unsigned long
#define MAX 100

int N=4;
int A[MAX]={1,2,3,4};
int SUM = 6;

ofstream fout("sum.out");

inttype two_p(int n)
{ return static_cast<inttype>(pow(2,n)); }

void count()
{
 int b[MAX], nb;
 inttype NN = two_p(N);
 for(inttype i=1; i<NN; i++)
 {
  int sum=0;
  nb = 0;
  for(int j=0; j<N; j++) if (two_p(j) & i)
  {
   sum+=A[j]; b[nb++]=j;
  }
  if (sum==SUM)
  {
   for (int k=0; k<nb; k++) fout << b[k] << " ";
   fout << endl;
  }
  cout << endl;
 }
}

int main()
{
 ifstream fin("sum.inp");
 int num;
 fin >> num;
 for (int i=0; i<num; i++)
 {
  fin >> N >> SUM;
  for (int j=0; j<N; j++) fin >> A[j];
  count();
  fout << endl;
 }
 return 0;
}

Задачи:
1. Да се промени програмата така, че да се повиши бързодействието й;
2. Програмата да може да работи при N=20.



2. Друг вариант на задачата за подмножества.

Даден е масив A с N елемента - естествени числа и цяло число S.  Да се намерят елементи на масива, чиято сума е S.

#include <iostream>

const int N=9;
int A[N]={7,7,7,4,5,6,7,8,9};
int SUM = 12;

bool count(int s, int m)
{
 if (s==0) return true;
 if (s<0) return false;
 for(int i=m; i<N; i++) if (count(s-A[i], i+1))
 {
  cout << A[i] << " "; return true;
 }
 return false;
}

int main()
{
 count(SUM, 0);
 cout << "\n";
 cin.get();
 return 0;
}



По-ефективни методи за решаване на подобни задачи

Задача за раницата
Динамично оптимиране