1. 程式人生 > >1268】和為K的組合 (揹包 或 dfs)

1268】和為K的組合 (揹包 或 dfs)

題幹:

給出N個正整陣列成的陣列A,求能否從中選出若干個,使他們的和為K。如果可以,輸出:"Yes",否則輸出"No"。

Input

第1行:2個數N, K, N為陣列的長度, K為需要判斷的和(2 <= N <= 20,1 <= K <= 10^9)  第2 - N + 1行:每行1個數,對應陣列的元素Aii (1 <= Aii <= 10^6)

Output

如果可以,輸出:"Yes",否則輸出"No"。

Sample Input

5 13
2
4
6
8
10

Sample Output

No

解題報告:

    很多人說這題用揹包,,,但是我一直想不通,1e9的空間,是怎麼用的揹包。。。這題資料量20,顯然是搜尋啊,,,複雜度o(2^n)不慫,不到30行就搞定了。

   如果要寫揹包的話思路上也是可以的,因為每個揹包體積1e6,20個加起來也才2e8,並且dp[j]=val,這裡可以保證jval<=j,因為物品的體積和價值是相同的啊。所以直接跑恰好裝滿問題,並且dp[k]=k就可以了。只要陣列開的下,,揹包也不難寫。

AC程式碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,k;
ll a[55];
bool dfs(ll step,ll cur) {
	if(cur  == k) return 1;
	if(step == n) return 0;
	if(cur+a[step+1] <= k) {
		if(dfs(step+1,cur+a[step+1])) return 1;
	}
	if(dfs(step+1,cur)) return 1;
	return 0;
}
int main()
{
	cin>>n>>k;
	for(int i = 1; i<=n; i++) cin>>a[i];
	sort(a+1,a+n+1); 
	if(dfs(0,0)) puts("Yes");
	else puts("No");
	return 0 ;
}

總結:搜尋題一定要注意啊,需要從(0,0)這個狀態開始搜尋,因為你直接(1,a[1])傳入引數了,那  不選第一個數 這個狀態就被沒有搜啊。。。