SRM 228 DIV1 Middle -BagsOfGold

問題


http://topcoder.bgcoder.com/print.php?id=768

ゴールドの山が順に並んでいる。
あらかじめ、それぞれの山にどれだけゴールドがあるかわかっている。

2人でこのゴールドの山の取りあいを行い、最初は自分のターン。
左端か右端のいずれかを選び、相手のターンに移る。

どちらも最適な選択をしたとき、自分が得られるゴールドと相手が得られるゴールドの差の最大値を求める。

解き方


dpの問題だが、自分のターンと相手のターンで選び方が異なる。
ターンの区別をなくし、次のターンは必ず相手は最善の選び方をすると考える。

そうすると、左端を選んだときに左端のスコアから相手が得られる最大のゴールドを引いたものと、右端を選んだときに右はじのスコアと相手から得られる最大のゴールドを引いたもののうち、最大のものを返してあげればよい。

コード


using namespace std;

#define all(c) (c).begin(),(c).end()
#define FORE(i,d,e) for(int i=d;i<e;i++)
#define FOR(i,s,e) for (int i = int(s); i != int(e); i++)
#define FORIT(i,c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ISEQ(c) (c).begin(), (c).end()

vector<int> b;
int dp[51][51];

class BagsOfGold {

public:

int calc(int left,int right){
if(left==right)return b[left];
if(dp[left][right]!=-1)return dp[left][right];

return dp[left][right]=max(b[left]-calc(left+1,right),b[right]-calc(left,right-1));
}

int netGain(vector<int> bags) {
b=bags;
int n=bags.size();
memset(dp,-1,sizeof(dp));

return calc(0,n-1);
}

};

Share this

Related Posts

Previous
Next Post »