NUMBERGAME (중하, p. 340)

NUMBERGAME (중하, p. 340)#

문제#

image.png

어떻게 풀었나?#

점화식#

dp[x][y][p] = v[x]부터 v[y]까지 숫자가 남았을 때, p차례일 때, 현우 점수 - 서하 점수

if(p==0) dp[x][y][p] = max({dp[x][y][p], dp[x+1][y][p^1]+v[x], dp[x][y-1][p^1]+v[y], dp[x+2][y][p^1], dp[x][y-2][p^1]});
if(p==1) dp[x][y][p] = min({dp[x][y][p], dp[x+1][y][p^1]-v[x], dp[x][y-1][p^1]-v[y], dp[x+2][y][p^1], dp[x][y-2][p^1]});

정답 코드#

#include <bits/stdc++.h>
using namespace std;
int n;
int v[51];
int dp[51][51][2];
bool chk[51][51][2];
const int INF = 0x3f3f3f3f;
int f(int x, int y, int p) {
    if(x>y || (x<0||y<0||x>=n||y>=n)) {
        return 0;
    }
    else if(x==y) {
        if(p==0) return v[x];
        else return -v[x];
    }
    int &ret = dp[x][y][p];

    if(chk[x][y][p]) return ret;
    chk[x][y][p] = true;

    if(p==0) {
        ret = -INF;
        ret = max({ret, f(x+1,y,p^1)+v[x], f(x,y-1,p^1)+v[y], f(x+2,y,p^1), f(x,y-2,p^1)});
    }
    else {
        ret = INF;
        ret = min({ret, f(x+1,y,p^1)-v[x], f(x,y-1,p^1)-v[y], f(x+2,y,p^1), f(x,y-2,p^1)});
    }
    return ret;
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int tc; cin >> tc;
    while(tc--) {
        cin >> n;
        for(int i=0; i<n; i++) {
            cin >> v[i];
        }

        memset(chk,false,sizeof(chk));
        printf("%d\n", f(0,n-1,0));
    }
    return 0;
}