羅区P3286 [SCOI2014]牙ボボモールツアー

タイトル:羅区P3286 [SCOI2014]牙ボボモールツアー

考え

デジタルDP

dalaoは、水の問題をDPこれはビット数であることを言って ...本当に私があまりにも料理だった、
彼らは出てくることは不可能です。この質問は、おそらく思考を理解し、単にそれを繰り返す、例として講義です。
まず、質問セクションの範囲と意味によれば、デジタルDPを見ることは容易です。
しかし、従来のデジタルDP異なる、我々は、各桁の最終組立ポイントを知りません。
だから我々は、同様にすべて最終的には最も低い位置(最初)に集まった石を厳選することがあります。呼ばれる、この場合の総費用\(費用\)は、単純なデジタルDPによって得ることができます。
しかし、これは明らかに、最適なソリューション、およびより少ない費用のために高い位置に集まった石のいくつかの数ではありません。だから我々は、少しずつ移動しました。
例えば、デジタル\(私は\) 石が今最初(最下位ビット)に集められ、我々はその後、第二位の石を移動する必要があります(私は\)\、高い位置および移動するための第二の位置のコストを削減します\(私は\)ルートのDP DPツリーの変化に類似した第1移動コストの上昇、の。\(デルタ(I)\)私は第一、第二の場所で一緒に動いたポリから石の数を表し、価格費やし削減(この文ビット長を)。とき(デルタ(i)が<0 \ )\ 、それは支出のコストが減少するが、増加されていないことを示し、その後、我々は、私は、そう私は石が二位に移動された置く石を移動しないでください。以上の動作に基づいて、総コストは、現在ある(コスト\ sum_ {I} = L ^ R&LTの\最大(デルタ(I)、0)\)\


\(\ sum_ {i = L } ^ Rの\最大(デルタ(i)は、0)\)は(DP、DPの第2の変換器のルートに類似)DPビットを計算するの数を再利用することができます。
今、我々は石を移動させることができる第一から第2の位置に変位し、その後、上述した方法の後、石は全て、第4端に第からずれ、第2の変位に対する第3から移動させることができます...石は最適な位置に移動させました

これは、コードに関連して理解されています。


コード

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll l,r,k,a[80],dp[80][4000][2][2];
ll dfs(int pos,int sum,bool lead,bool limit){
    if(pos==0) return sum;
    ll &ans=dp[pos][sum][lead][limit];
    if(ans!=-1) return ans;
    ans=0;
    for(int i=0,up=limit?a[pos]:k-1;i<=up;++i){
        if(!i&&lead) ans+=dfs(pos-1,0,true,limit&&i==a[pos]);
        else ans+=dfs(pos-1,sum+i*(pos-1),false,limit&&i==a[pos]);
    }
    return ans;
}
ll dfs(int to,int pos,int sum,bool lead,bool limit){
    if(pos==0) return max(sum,0);
    ll &ans=dp[pos][sum+500][lead][limit];
    if(ans!=-1) return ans;
    ans=0;
    for(int i=0,up=limit?a[pos]:k-1;i<=up;++i){
        if(!i&&lead) ans+=dfs(to,pos-1,0,true,limit&&i==a[pos]);
        else if(pos>=to) ans+=dfs(to,pos-1,sum+i,false,limit&&i==a[pos]);
        else ans+=dfs(to,pos-1,sum-i,false,limit&&i==a[pos]); 
    }
    return ans;
}
ll solve(ll num){
    memset(dp,-1,sizeof(dp));
    int len=0;
    while(num) a[++len]=num%k,num/=k;
    ll res=dfs(len,0,true,true);
    for(int i=2;i<=len;++i){
        memset(dp,-1,sizeof(dp));
        res-=dfs(i,len,0,true,true);
    }
    return res;
}
int main(){
    scanf("%lld%lld%d",&l,&r,&k);
    printf("%lld\n",solve(r)-solve(l-1));
    return 0;
}

おすすめ

転載: www.cnblogs.com/yu-xing/p/11311698.html