1. 程式人生 > >Codeforces 1110D Jongmah [DP]

Codeforces 1110D Jongmah [DP]

esp define 做出 isp void new ont 三元組 www.

洛谷

Codeforces


我…我我把這…這這題切了???

說實話這題的確不難,只是我看到有大佬沒做出來有點慌……

突然發現這題是我在洛谷的第500個AC呢。那就更要寫篇題解紀念一下了。


思路

容易想到一個貪心:把有三個的都取完,然後隨便搞後面的。

這顯然是錯的……

但你進一步思考發現:對於三元組\(\{x-2,x-1,x\}\),它最多取\(2\)次,否則就可以變成多個\(\{x,x,x\}\)後再重新搞。

那麽就容易想到DP了。

\(dp_{i,j,k}\)表示考慮到第\(i\)位,欽定第\(i\)位已經用掉了\(j\)個,第\(i-1\)位已經用掉了\(k\)個,能得到的三元組個數。

轉移時枚舉選幾個\(\{i-2,i-1,i\}\)

,得到轉移方程:

\[ dp_{i,j,k}=\max_{l=0}^2\{dp_{i-1,k+l,l}+\lfloor \frac{cnt_i-l-j}{3}\rfloor +l\} \]

最後\(ans=dp_{m,0,0}\)

註意DP時一個位置會被欽定兩次,所以\(0\leq j,k\leq 4\)


代碼

#include<bits/stdc++.h>
namespace my_std{
    using namespace std;
    #define pii pair<int,int>
    #define fir first
    #define sec second
    #define MP make_pair
    #define rep(i,x,y) for (int i=(x);i<=(y);i++)
    #define drep(i,x,y) for (int i=(x);i>=(y);i--)
    #define go(x) for (int i=head[x];i;i=edge[i].nxt)
    #define sz 1010101
    typedef long long ll;
    template<typename T>
    inline void read(T& t)
    {
        t=0;char f=0,ch=getchar();
        double d=0.1;
        while(ch>‘9‘||ch<‘0‘) f|=(ch==‘-‘),ch=getchar();
        while(ch<=‘9‘&&ch>=‘0‘) t=t*10+ch-48,ch=getchar();
        if(ch==‘.‘)
        {
            ch=getchar();
            while(ch<=‘9‘&&ch>=‘0‘) t+=d*(ch^48),d*=0.1,ch=getchar();
        }
        t=(f?-t:t);
    }
    template<typename T,typename... Args>
    inline void read(T& t,Args&... args){read(t); read(args...);}
    void file()
    {
        #ifndef ONLINE_JUDGE
        freopen("a.txt","r",stdin);
        #endif
    }
//  inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;

int n,m;
int cnt[sz];
int dp[sz][5][5];

int main()
{
    file();
    int x;
    read(n,m);
    rep(i,1,n) read(x),++cnt[x];
    memset(dp,~0x3f,sizeof(dp));
    dp[0][0][0]=0;
    rep(i,0,min(4,cnt[1])) dp[1][i][0]=(cnt[1]-i)/3;
    rep(i,2,m)
    {
        rep(j,0,4)
        {
            if (j>cnt[i]) break;
            rep(k,0,4)
            {
                if (k>cnt[i-1]) break;
                rep(l,0,2)
                {
                    if (j+l>cnt[i]||k+l>cnt[i-1]||l>cnt[i-2]||k+l>4) break;
                    dp[i][j][k]=max(dp[i][j][k],dp[i-1][k+l][l]+(cnt[i]-l-j)/3+l);
                }
            }
        }
    }
    cout<<dp[m][0][0];
}

Codeforces 1110D Jongmah [DP]