สมมติว่ามีแก๊งค์ที่มีคนจีและรายการอาชญากรรมต่างๆ ที่พวกเขาสามารถก่อได้ อาชญากรรมครั้งที่ i สร้างผลกำไรมูลค่ากำไร[i] และต้องการให้สมาชิกแก๊งค์[i]เข้าร่วม
หากสมาชิกแก๊งมีส่วนร่วมในอาชญากรรมอย่างใดอย่างหนึ่ง ว่าเขาไม่สามารถมีส่วนร่วมในอาชญากรรมอื่นได้ ตอนนี้ ให้เรากำหนดรูปแบบการทำกำไรของกลุ่มย่อยของอาชญากรรมเหล่านี้ที่สร้างผลกำไรอย่างน้อย P และจำนวนสมาชิกทั้งหมดที่เข้าร่วมในกลุ่มย่อยของอาชญากรรมนั้นมากที่สุด G
เราต้องหาว่าสามารถเลือกแบบแผนได้กี่แบบ? คำตอบอาจมีขนาดใหญ่มาก ให้คืนค่าเป็นโมดูล 10^9 + 7.
ดังนั้น หากอินพุตเป็นเหมือน G =5, P =3 และ group =[2,2], profit =[2,3] ผลลัพธ์จะเป็น 2
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
-
ยกเลิก :=0
-
กำหนดขนาดอาร์เรย์ 2 มิติหนึ่ง dp (G + 1) x (P + 1)
-
dp[0, 0] :=1
-
สำหรับการเริ่มต้น k :=0 เมื่อ k <ขนาดของกลุ่ม ให้อัปเดต (เพิ่ม k ขึ้น 1) ให้ทำ -
-
p :=profit[k], g :=group[k]
-
สำหรับการเริ่มต้น i :=G - g เมื่อ i>=0, อัปเดต (ลด i โดย 1) ทำ -
-
สำหรับการเริ่มต้น j :=P เมื่อ j>=0, อัปเดต (ลด j โดย 1) do−
-
dp[i + g, ค่าต่ำสุดของ P และ j + p]
-
dp[i + g, ค่าต่ำสุดของ P และ j + p]
-
-
-
-
สำหรับการเริ่มต้น i :=0 เมื่อ i <=G อัปเดต (เพิ่ม i ขึ้น 1) ทำ -
-
ret :=ret + dp[i, P]
-
ret :=ret mod m
-
-
รีเทิร์น
ให้เราดูการใช้งานต่อไปนี้เพื่อความเข้าใจที่ดีขึ้น -
ตัวอย่าง
#include <bits/stdc++.h> using namespace std; const int m = 1e9 + 7; class Solution { public: int profitableSchemes(int G, int P, vector<int> &group, vector<int> &lprofit) { int ret = 0; vector<vector<int>> dp(G + 1, vector<int>(P + 1)); dp[0][0] = 1; for (int k = 0; k < group.size(); k++) { int p = profit[k]; int g = group[k]; for (int i = G - g; i >= 0; i--) { for (int j = P; j >= 0; j--) { dp[i + g][min(P, j + p)] += dp[i][j]; dp[i + g][min(P, j + p)] %= m; } } } for (int i = 0; i <= G; i++) { ret += dp[i][P]; ret %= m; } return ret; } }; main(){ Solution ob; vector<int> v = {2,2}, v1 = {2,3}; cout << (ob.profitableSchemes(5,3,v, v1)); }
อินพุต
5, 3, [2,2], [2,3]
ผลลัพธ์
2