สมมติว่าเรามีรายการของจำนวนเต็มที่ไม่ติดลบ, a1, a2, ..., an, และค่าอื่นที่เป็นเป้าหมาย, S. ตอนนี้เรามี 2 สัญลักษณ์ + และ - . สำหรับจำนวนเต็มแต่ละจำนวน เราควรเลือกหนึ่งรายการจาก + และ - เป็นสัญลักษณ์ใหม่ เราต้องหาวิธีกำหนดสัญลักษณ์ให้ได้จำนวนเต็มเท่ากับค่าเป้าหมาย S ดังนั้นถ้าตัวเลขเป็น [1,1,1,1,1] และ S =3 ผลลัพธ์จะเป็น 5 ตามที่รวมกันคือ – 1 + 1 + 1 + 1 + 1 =3, + 1 – 1 + 1 + 1 + 1 =3, + 1 + 1 – 1 + 1 + 1 =3, + 1 + 1 + 1 – 1 + 1 =3, + 1 + 1 + 1 + 1 – 1 =3 ดังนั้นจึงมีห้าวิธีในการมอบหมาย
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
- สร้างตาราง dp ขนาด 21 x 2001 หนึ่งตาราง เติมด้วย – 1 ซึ่งจะใช้สำหรับแนวทางการเขียนโปรแกรมแบบไดนามิก
- เมธอดแบบเรียกซ้ำจะเรียกว่า Solve() สิ่งนี้จะใช้ pos, array v, tempSum และผลรวมจริง S ซึ่งจะทำหน้าที่ดังต่อไปนี้ -
- ถ้า pos เท่ากับขนาดของอาร์เรย์ v ให้คืนค่า จริง ถ้า s =tempSum ไม่เช่นนั้น จะเป็นเท็จ
- ถ้า dp[pos, tempSum + 1000] ไม่ใช่ -1 ให้คืนค่า dp[pos, tempSum + 1000]
- ตอบ :=แก้ (pos + 1, v, tempSum – v[pos], s) + แก้ (pos + 1, v, tempSum + v[pos], s)
- dp[pos, tempSum + 1000] =ตอบ
- คืนสินค้า
- เรียก Solve() จากส่วนหลักโดยใช้พารามิเตอร์ Solve(0, nums, 0, s)
ตัวอย่าง(C++)
ให้เราดูการใช้งานต่อไปนี้เพื่อทำความเข้าใจ −
#include <bits/stdc++.h> using namespace std; class Solution { public: int dp[21][2001]; int solve(int pos, vector <int> v, int tempSum, int s){ if(pos == v.size()){ return s == tempSum; } if(dp[pos][tempSum+1000]!=-1)return dp[pos][tempSum+1000]; int ans = solve(pos+1,v,tempSum-v[pos],s) +solve(pos+1,v,tempSum+v[pos],s); dp[pos][tempSum+1000] = ans; return ans; } int findTargetSumWays(vector<int>& nums, int s) { int n = nums.size(); if(s>1000)return 0; for(int i =0;i<21;i++){ for(int j =0;j<2001;j++){ dp[i][j] = -1; } } return solve(0,nums,0,s); } }; main(){ Solution ob; vector<int> v = {1,1,1,1,1}; cout << ob.findTargetSumWays(v, 3); }
อินพุต
[1,1,1,1,1] 3
ผลลัพธ์
5