NOIP2017赛前模拟 分玩具

Description:
豆豆和豆沙正在分一些玩具,每个玩具有一个好玩值,每个人可以拿走任意数量的玩具,获得的愉快度为最小的好玩值。现在豆豆先拿,每个人轮流操作,直到没有玩具可以拿。豆豆想知道他能比豆沙多出多少愉快度?

Input:
第一行 N 表示玩具个数。
接下来一行 N 个整数表示第 i 个玩具的好玩值。

Output:
输出一个整数表示最多多出的愉快度。

Sample Input:
3
1 3 1

Sample Output:
2

数据范围:
对于 30% 的数据,N≤10。
对于 70% 的数据,N≤1000。
对于 100 %的数据,N≤1000000,0≤数值范围≤10^9。

出题人的提醒:
1、豆豆和豆沙两位dalao都是绝顶聪明的,不会做出故意让游戏输的行为;
2、愉快度为每轮结算,轮于轮之间累加计算。

题解:
1、通过观察发现,最优情况都是从大到小选的;
2、这是一道DP题,定义 dp[ i ] 表示当前还剩i个物品的最优解;
3、因为对于两个人来说,目的都是使两人愉快度的差值最大,所以上一轮的最优值对于下一轮的先手来说是不好的,所以方程为:
dp[ i ] =max( a[ j + 1] + dp[ j ] ) (0 < j < i )
4、看这个方程 n^2 肯定是不行的,再看一眼,显然单调队列优化,不解释了

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int n,a[1000005];
long long max_ans,dp[1000005];
//---------------------
inline int Readint(){
    int i=0,f=1;char ch;
    for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<1)+(i<<3)+ch-'0';
    return i*f;
}
//---------------------
int main(){
    //freopen("toy.in","r",stdin);
    //freopen("toy.out","w",stdout);

    n=Readint();
    for(int i=1;i<=n;i++) a[i]=Readint();
    sort(a+1,a+1+n);
    max_ans=a[1];
    for(int i=1;i<=n;i++){
        dp[i]=max_ans;
        max_ans=max((long long)a[i+1]-dp[i],max_ans);
    }
    cout<return 0;
}

后记:
这道题,还是应该先确定选玩具的策略,即从大往小选 ,然后再去确定状态和方程,果然 dp 还是做的太少了,还要继续加油。

你可能感兴趣的:(考试总结)