สมมติว่ามีสองคนที่อลิซและบ็อบ พวกเขากำลังเล่นเกมต่อด้วยกองหิน มีกองจำนวนหนึ่งวางเรียงเป็นแถว และแต่ละกองมีจำนวนเต็มบวกของหินในกองอาร์เรย์[i] เป้าหมายของเกมคือการจบด้วยหินมากที่สุด อลิซและบ็อบผลัดกัน โดยอลิซเริ่มก่อน เริ่มแรก M =1 ในเทิร์นของผู้เล่นแต่ละคน ผู้เล่นนั้นสามารถเอาหินทั้งหมดในกอง X อันแรกที่เหลืออยู่ที่นี่ 1 <=X <=2M จากนั้นเราตั้งค่า M =สูงสุด (M, X) เกมจะจบลงเมื่อไม่มีก้อนหินเหลืออยู่ ดังนั้นหากกอง =[2,7,9,4,4] ผลลัพธ์จะเป็น 10 นี่เป็นเพราะถ้าอลิซรับหนึ่งกองในตอนเริ่มต้น บ็อบก็จะรับสองกอง แล้วอลิซก็จะรับอีก 2 กอง อลิซสามารถรับ 2 + 4 + 4 =10 กองทั้งหมดในมือของเธอ ถ้าอลิซรับสองกองในตอนเริ่มต้น บ็อบก็สามารถรับทั้งสามกองที่เหลือได้ ในกรณีนี้ อลิซได้ 2 + 7 =9 กอง ดังนั้นเราจะได้ผลตอบแทน 10 เนื่องจากมีขนาดใหญ่
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
- สร้างฟังก์ชันเรียกซ้ำหนึ่งฟังก์ชันที่เรียกว่า Solve ซึ่งจะรับอาร์เรย์ i, m และเมทริกซ์หนึ่งตัวที่เรียกว่า dp
- ถ้า i>=ขนาดของ arr ให้คืนค่า 0
- ถ้า dp[i, m] ไม่ใช่ -1 ให้คืนค่า dp[i, m]
- ถ้า i – 1 + 2m>=ขนาดของอาร์เรย์ ให้คืนค่า arr[i]
- op :=inf
- สำหรับ x ในช่วง 1 ถึง 2 เมตร
- op :=นาทีของ op, แก้ (arr, i + x, สูงสุดของ x และ m, dp)
- dp[i, m] :=arr[i] – op
- ส่งคืน dp[i, m]
- วิธีการจริงจะเป็นเช่น −
- n :=ขนาดของอาร์เรย์ไพล์ สร้างหนึ่งอาร์เรย์ที่เรียกว่า arr ของขนาด n
- arr[n - 1] :=กอง[n – 1]
- สำหรับ i :=n – 2 เหลือ 0
- arr[i] :=arr[i + 1] + กอง[i]
- สร้างเมทริกซ์ขนาดหนึ่งตัว (n + 1) x (n + 1) แล้วเติมด้วย -1
- ผลตอบแทนการแก้(arr, 0, 1, dp)
ให้เราดูการใช้งานต่อไปนี้เพื่อความเข้าใจที่ดีขึ้น -
ตัวอย่าง
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
void printVector(vector <int> v){
for(int i =0;i<v.size();i++)cout << v[i] << " ";
cout << endl;
}
int stoneGameII(vector<int>& piles) {
int n = piles.size();
vector <int> arr(n);
arr[n-1] = piles[n-1];
for(int i = n-2;i>=0;i--)arr[i] = arr[i+1] + piles[i];
vector < vector <int> > dp(n+1,vector <int> (n+1,-1));
return solve(arr,0,1,dp);
}
int solve(vector <int> arr, int i, int m, vector < vector <int> > &dp){
if(i >=arr.size())return 0;
if(dp[i][m]!=-1)return dp[i][m];
if(i-1+2*m >=arr.size())return arr[i];
int opponentCanTake = INT_MAX;
for(int x =1;x<=2*m;x++){
opponentCanTake = min(opponentCanTake,solve(arr,i+x,max(x,m),dp));
}
dp[i][m] = arr[i] - opponentCanTake;
return dp[i][m];
}
};
main(){
vector<int> v = {2,7,9,4,4};
Solution ob;
cout <<(ob.stoneGameII(v));
} อินพุต
[2,7,9,4,4]
ผลลัพธ์
10