給定一個數組和一個數k
如果在這個數組能任意找到二個數組相加得到給定的k 便返回true 否則返回false
樣例輸入
6
2 34 12 4 5 8
9
輸出
true
分析:
同樣先自頂向下分析
拿上面的例子 從最後的數字8開始向前推 對於每個數字有取或不取二種方案,
如果取
subset(arr,i-1,s-arr[i])
表示那要求得的值減去取的當前值,接着在從前面 i-1 個數中找能湊成
s-arr[i] 的
如果不取
那就是從前面 i-1個數中湊 s
接着找到遞歸出口
- 如果s等於0返回true
- 如果只剩最後一個數,但這個數不等於你需要的數 返回false 反之返回true
- 如果要減去的數比自身還要大 直接不取這個數
#include<iostream>
#include<algorithm>
using namespace std;
int arr[101];
int n;
bool rec_subset(int i, int total) {
if (total == 0)
return true;
else if (i == 0)
return arr[i] == total;
else if (arr[i] > total)
return rec_subset(i - 1, total);
else
return rec_subset(i - 1, total - arr[i]) || rec_subset(i - 1, total);
}
int main()
{
cin >> n;
for (int i = 0;i < n;i++)
cin >> arr[i];
int total;
cin >> total;
cout << rec_subset(n - 1, total);
}
動態規劃
二維數組的行就代表arr的每一行下標 列就代表0-total
遞推 所以先初始化第0行和第0列
根據上面的遞歸出口:
第1行到第n-1行的第0列都爲true 因爲數組還沒有用完total就已經爲0了
第0行的每一列都爲false除了下標爲arr[0]的 因爲第0行表示就剩這一個數字了 只有和我需要的數字相等才爲true
#include<iostream>
using namespace std;
int dp[100][100];
int n;
int total;
int arr[100];
int main()
{
cin >> n;
for (int i = 0;i < n;i++)
cin >> arr[i];
cin >> total;
for (int i = 0;i < n;i++)
dp[i][0] = 1;
dp[0][arr[0]] = 1;
for (int i = 1;i <n;i++) {
for (int j = 1;j <= total;j++) {
if (arr[i] > j)
dp[i][j] = dp[i - 1][j];//如果比需要的大直接不取這個數字 在上面的i-1個裏面取
else {
//取自己或者不取自己 有一個滿足即可
int a = dp[i][j - arr[i]];
int b = dp[i-1][j];
dp[i][j] = a || b;
}
}
}
cout << dp[n - 1][total-1]<<endl;
}