LGOJ P5020の金融システム

オリジナルタイトルpress_here!
トピックをオーバープルするのが面倒

問題の解

状態遷移方程式を考えてみます。

\ [Dpは(I)= DP(I-1)+ [a_iをA_1があり、A_2、...、A_ {I-1}何らかの線形結合]、\クワッドI> 1 \]

ここで、角括弧で真である命題である\(1 \) そうでなければ\(0 \)

そして、メモリ検索

取得する方法について考えた後、暴力的な最終のかナップザック問題にメモリを追加しました......とにかく、AC Guannameduoではありません

式はに減らすことができます。

\ [DP(I)= DP(I-1)+ [!DFS(I-1、a_iを)]、\クワッドI> 1 \]

ここで、dfs(int pos,int rest)\(A_ {POS} \)である\(A_1、A_2、...、 A_ {POS-1} \) の特定の線形結合で\(1 \) そうでなければ\(0 \)

コード:

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    char c=getchar();int x=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        x=x*10+c-'0';
    return x;
}
int n,m,a[105],f[105][25005],dp[105];

bool dfs(int pos,int rest)
{
    if(rest==0)return 1;
    if(pos==0)return 0;
    if (f[pos][rest]!=-1)return f[pos][rest];
    bool res=0;
    for(int i=0;rest-i*a[pos]>=0;i++)
        res|=dfs(pos-1,rest-i*a[pos]);
    return f[pos][rest]=res;
}

int main()
{
    int T=read();
    while(T--)
    {
        memset(a,0,sizeof(a));
        n=read();
        for(int i=1;i<=n;i++)a[i]=read();
        sort(a+1,a+n+1);
        memset(f,-1,sizeof(f));
        memset(dp,0,sizeof(dp));
        dp[1]=1;
        for(int i=2;i<=n;i++)dp[i]=dp[i-1]+(!dfs(i-1,a[i]));
        printf("%d\n",dp[n]);
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/kion/p/11823925.html