89 k數和
阿新 • • 發佈:2018-07-29
length 代碼 color aps 實的 數據 方程 ref rip
好吧,動態規劃就動態規劃。剛做過背包問題,背包問題中用背包容量作為動態數組一個維度,另一個維度是取0~i個物體,dp值是當前最大容量。而這道題,目標數字相當於背包容量,要作為一個維度,但與背包問題不同的是,這道題是從前i個中取出若幹個,又多出一個維度,所以要用三維動態數組,dp值表示當前方案數,大爺的……
dp【i】【j】【t】表示從前i個數中取出j個,這些數的和要等於t,有多少種方案。
狀態轉移方程:dp【i】【j】【k】=dp【i-1】【j】【t】+dp【i-1】【j-1】【t-A【i】】(當然前提是t>=A【i】);
即
值得註意的是,如果j為0並且t也為0,則dp【i】【j】【t】=1,即是說從任意集合裏拿出0個數使其和為0,這種情況只有一種方案,就是不取任何數。
AC代碼:(註意代碼實現的時候對i做了處理,因為第一個數下標是0,或者也可以單獨處理i=0的情況)
原題網址:https://www.lintcode.com/problem/k-sum/description
描述
給定n個不同的正整數,整數k(k < = n)以及一個目標數字。
在這n個數裏面找出K個數,使得這K個數的和等於目標數字,求問有多少種方案?
您在真實的面試中是否遇到過這個題?樣例
給出[1,2,3,4],k=2, target=5,[1,4] and [2,3]是2個符合要求的方案
標簽
LintCode 版權所有 動態規劃(DP) 思路:最開始參照了k數和Ⅱ用遞歸來做,結果只通過18%的數據就Time Limit Exceeded了。點開標簽一看,要用動態規劃……一口老血。
dp[i][j][t]=dp[i-1 ][j][t];
if (t>=A[i])//註意是大於等於;
{
dp[i][j][t]+=dp[i-1][j-1][t-A[i]];
}
意思就是,每個元素都有兩種狀態,取或者不取:
(1)若不取A[i]這個值,當前方案數等於從前i-1個數中取j個使其和為t的方案數,即dp[i - 1][j][t]。
(2)若取當前值A[i],則當前方案數等於從前i-1個數中取j個使其和為t的方案數再加上考慮A[i]的情況,即dp[i - 1][j - 1][t - A[i]](前提是t - A[i]要大於等於0)。
class Solution {
public:
/**
* @param A: An integer array
* @param k: A positive integer (k <= length(A))
* @param target: An integer
* @return: An integer
*/
int kSum(vector<int> &A, int k, int target) {
// write your code here
int size=A.size();
if (target<0)
{
return 0;
}
vector<vector<vector<int>>> dp(size+1,vector<vector<int>>(k+1,vector<int>(target+1,0)));
for (int i=0;i<=size;i++)
{
for (int j=0;j<=k;j++)
{
for (int t=0;t<=target;t++)
{
if (j==0&&t==0)//前i個數中取0個和為0只有一種方案,就是不取任何數;
{
dp[i][j][t]=1;
}
else if (!(i==0||j==0||t==0))
{
dp[i][j][t]=dp[i-1][j][t];
if (t>=A[i-1])//註意是大於等於;
{
dp[i][j][t]+=dp[i-1][j-1][t-A[i-1]];
}
}
}
}
}
return dp[size][k][target];
}
};
空間優化: 一道題做了好久……各種細節出錯,不參照答案寫不出來,多維動態數組對我而言還是有一定難度的,哭…… 參考: lintcode: k Sum 解題報告 LintCode-k數和 LintCode -- k數和 標記下我最開始的遞歸代碼:
class Solution {
public:
/**
* @param A: An integer array
* @param k: A positive integer (k <= length(A))
* @param target: An integer
* @return: An integer
*/
int kSum(vector<int> &A, int k, int target) {
// write your code here
int result=0;
if (A.empty())
{
return result;
}
ksum(A,k,target,0,0,0,result);
return result;
}
void ksum(vector<int> &A, int k, int target,int sum,int ind,int size,int &result)
{
if (size==k)
{
if (sum==target)
{
result++;
}
return ;
}
if (ind>=A.size())
{
return ;
}
ksum(A,k,target,sum+A[ind],ind+1,size+1,result);
ksum(A,k,target,sum,ind+1,size,result);
}
};
89 k數和