問題:
先輸入兩個數,一個和sum,一個數據個數n,然後接著n個數為具體的數據,求n個數裡面的數相加為sum的組合並輸出。如果沒有則輸出:NONE
限制和剪枝:
1、輸出不能有重復的情況,即只能是不同的組合。
代碼裡面那個判重關鍵理解了好久。。。感覺還是半懂。。T_T 。。
如果沒有那兩行代碼,輸出的就有很多重復情況。
一開始不知道怎麼判重,後來想到字典樹,又沒有想到字典樹怎麼表示,後來發現可以用二維數組把所有情況全存著,然後最後輸出時再進行判重,不過感覺好麻煩,還要開辟一個二維數組存所有
情況,然後再開一個輸出而為數組,在所有情況的數組中要和輸出數組進行比較,看是否已經存在。
感覺這種方法好麻煩,而且時間復雜度應該也比較高,但是在百度的時候發現好像有人這樣過了。。。反正看到有人用這種方法貼出了代碼。。
AC代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[500],out[500];
int sum,n,p;
void Dfs(int nowsum, int k, int start)
{
int nextsum,i;
int x;
if(nowsum > sum)
{
return ;
}
// printf("k:%d nowsum:%d\n",k,nowsum);
if(nowsum == sum)
{
p++; //標記有存在的組合
printf("%d",out[0]);
for(i = 1; i < k; i++)
{
printf("+%d",out[i]);
}
printf("\n");
return ;
}
x = -1; //初始化起點位置(判重關鍵)
for(i = start; i < n; i++)
{
// printf("i:%d x:%d a[i]:%d\n",i,x,a[i]);
if(x != a[i]) //判重關鍵
{
x = a[i];
out[k] = a[i];
nextsum = nowsum + a[i];
Dfs(nextsum,k+1,i+1);
}
}
return ;
}
int main()
{
int i,nowsum,k;;
while(scanf("%d%d",&sum,&n)&&sum||n)
{
nowsum = k = p = 0;
for(i = 0; i < n; i++)
{
scanf("%d",&a[i]);
}
printf("Sums of %d:\n",sum);
Dfs(nowsum,k,0);
if(p == 0)
{
printf("NONE\n");
}
}
return 0;
}