試題 算法訓練 和爲T
題目描述:
資源限制
時間限制:1.0s 內存限制:256.0MB
問題描述
從一個大小爲n的整數集中選取一些元素,使得它們的和等於給定的值T。每個元素限選一次,不能一個都不選。
輸入格式
第一行一個正整數n,表示整數集內元素的個數。
第二行n個整數,用空格隔開。
第三行一個整數T,表示要達到的和。
輸出格式
輸出有若干行,每行輸出一組解,即所選取的數字,按照輸入中的順序排列。
若有多組解,優先輸出不包含第n個整數的;若都包含或都不包含,優先輸出不包含第n-1個整數的,依次類推。
最後一行輸出總方案數。
樣例輸入
5
-7 -3 -2 5 9
0
樣例輸出
-3 -2 5
-7 -2 9
2
數據規模和約定
1<=n<=22
T<=maxlongint
集合中任意元素的和都不超過long的範圍
解題思路:
(如果大家不會動態規劃,可以看一下這個up主的視頻講解,絕對一次就懂非常清晰)
動態規劃(注意倒着遍歷,因爲題目要求若有多組解,優先輸出不包含第n個整數的;若都包含或都不包含,優先輸出不包含第n-1個整數的,依次類推)
從n的位置開始遍歷,每一個位置可以選擇也可以不選擇,有兩個狀態,但是優先不選擇的那一邊。還有注意代碼中展示的終止條件(爲什麼不只是t的值爲T且數組中有數值的時候輸出)
AC代碼:
#include <stdio.h>
long int a[30];
long int b[30];
long int T;
int n;
long int sum=0;
void f(int long t,int pos,int i )//i爲起始遍歷的索引位置 ,pos爲數組中符合答案的元素個數
{
int j;
if(t==T&&pos!=0&&i<1)
{ //終止條件 注意全部遍歷完再進行判斷(防止 -1 1 -2 2 3 -3的特例) 並且 不能不選
sum++;//sum爲答案的個數
for(j=pos-1; j>=0; j--) //倒着遍歷輸出
printf("%ld ",b[j]);
printf("\n");
}
else
{
if(i<1)
return ;//遍歷到數組第一項還未滿足t==T;則返回
f(t,pos,i-1);
b[pos]=a[i];
f(t+a[i],pos+1,i-1);
}
}
int main()
{
int i;
scanf("%d",&n);
for(i=1; i<=n; i++)
scanf("%ld",&a[i]);
scanf("%ld",&T);
f(0,0,n);
printf("%d\n",sum);
return 0;
}