分金子

来源:互联网 发布:华师大网络教育好不好 编辑:程序博客网 时间:2024/04/29 22:37

分金子
题目描述:
A、B两伙马贼意外地在一片沙漠中发现了一处金矿,双方都想独占金矿,但各自的实力都不足以吞下对方,经过谈判后,双方同意用一个公平的方式来处理这片金矿。处理的规则如下:他们把整个金矿分成n段,由A、B开始轮流从最左端或最右端占据一段,直到分完为止。
马贼A想提前知道他们能分到多少金子,因此请你帮忙计算他们最后各自拥有多少金子?(两伙马贼均会采取对己方有利的策略)

这里写图片描述

这是2017年360春招的编程最后一题,题目很有意思,两个马贼互相博弈。
解题思路:动态规划
dp[i][j]:从第i堆到第j堆,能够拿到的最多金矿。
递推公式:dp[i][j]=sum(i->j)-min(dp[i+1][j],dp[i][j+1])
min(dp[i+1][j],dp[i][j+1]):下一个人拿的最少的金矿
初始条件:dp[i][i]=a[i] //每一堆的金矿数

为了避免递归超时,选择了递推的方式。

#include<iostream>#include<cmath>using namespace std;int main(){    int t;    cin>>t;    for(int k=0;k<t;k++){        int n;        cin>>n;        int dp[n+1][n+1];        int a[n+1];        for(int i=1;i<n+1;i++)            cin>>a[i];        a[0]=0;        int sum[n+1];        sum[0]=0;        for(int i=1;i<n+1;i++)            sum[i]=sum[i-1]+a[i];        for(int i=1;i<n+1;i++)            dp[i][i]=a[i];        for(int i=1;i<n;i++)            for(int j=1;j+i<=n;j++)                dp[j][i+j]=(sum[i+j]-sum[j-1])-min(dp[j+1][i+j],dp[j][i+j-1]);        cout<<"Case #"<<k+1<<": "<<dp[1][n]<<" "<<sum[n]-dp[1][n]<<endl;    }    return 0;}
2 0
原创粉丝点击