LGOJ P5020 货币系统

原题press_here!
懒得再抠题目过来了

問題の解

考虑状态转移方程:

\[ dp(i)=dp(i-1)+[a_i是a_1,a_2,...,a_{i-1}的某种线性组合], \quad i > 1 \]

其中,中括号内的命题为真时其值为\(1\),否则为\(0\)

然后是记忆化搜索

想着怎么样暴力搞定结果最后加了个记忆化之后还是变成了背包问题……反正都是AC不管那么多了

方程可以化为:

\[ dp(i)=dp(i-1)+ [!dfs(i-1,a_i)], \quad 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