zoukankan      html  css  js  c++  java
  • 牛客小白月赛30 J.小游戏 (DP)

    • 题意:给你一组数,每次可以选择拿走第(i)个数,得到(a[i])的分数,然后对于分数值为(a[i]-1)(a[i]+1)的值就会变得不可取,问能得到的最大分数是多少.
    • 题解:(a[i])最大取(2e5),那我们可以枚举([1,2e5])的所有数字,用桶记录每个数出现的次数(cnt[x]),对于当前所枚举的数(x),我们有两种选择:

    1.选
    2.不选
    假如我们选择(x),那么(x-1)肯定不能选的,不难想,最优的情况一定是从最近的(x-2)转移过来并且加上当前的贡献,假如我们不选的话,那么我们的状态就应该从上一个数(x-1)转移过来,所以状态转移方程就是(dp[i]=max(dp[i-1],dp[i-2]+i*cnt[i])).

    • 代码:
    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
    
    int n;
    int cnt[N];
    ll dp[N];
    ll ans=0;
    
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    	cin>>n;
    	rep(i,1,n){
    		int x;
    		cin>>x;
    		cnt[x]++;
    	}
    
    	dp[1]=max(0,cnt[1]);
    
    	rep(i,0,200010){
    	    dp[i]=max(dp[i-1],dp[i-2]+i*cnt[i]);			
    		ans=max(ans,dp[i]);
    	}
    
    	cout<<ans<<'
    ';
    
        return 0;
    }
    
  • 相关阅读:
    P1268 树的重量
    P2419 [USACO08JAN]牛大赛Cow Contest
    P1306 斐波那契公约数
    P2905 [USACO08OPEN]农场危机Crisis on the Farm
    P1081 开车旅行
    P2906 [USACO08OPEN]牛的街区Cow Neighborhoods
    P1550 [USACO08OCT]打井Watering Hole
    P2746 [USACO5.3]校园网Network of Schools
    P1613 跑路
    【BZOJ4868】期末考试(整数三分)
  • 原文地址:https://www.cnblogs.com/lr599909928/p/14097737.html
Copyright © 2011-2022 走看看