狂刷DP

不行啊都开始卷了,补一下弱项

P5020 货币系统

个人认为题面写复杂了,真没啥必要。。。
很明显的背包问题。
\(dp_i\) 为面值为 \(i\) 的钱最多需要多少张货币来表示。
那么就直接跑背包就行了,表示不了的为 \(dp_i=-inf\),能表示的且只有它自己能的为 \(dp_i=1\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e4+5;
const int INF=0x7f7f7f7f;

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

int T,n;
int a[5005],dp[MAXN];//dp[i]表示面值为i的钱最多要多少张货币来表示

int main()
{
    T=read();
    while(T--)
    {
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        memset(dp,-INF,sizeof(dp));
        dp[0]=0;
        for(int i=1;i<=n;i++)
            for(int j=a[i];j<=25000;j++)
                dp[j]=max(dp[j],dp[j-a[i]]+1);
        int ans=0;
        for(int i=1;i<=n;i++)
            if(dp[a[i]]==1) ans++;
        printf("%d\n",ans);
    }
    return 0;
}

P4290 玩具取名

为什么感觉DP的题面都好难懂。。。

这道题大概就是给定一个变换规则,然后问哪一个字母可以经过瞎购吧变换变成题目给的名字。
这很明显区间DP吧。

\(dp_{i,j,k}\) 表示 \(i\)\(j\) 这一区间内的名字能否用字母 \(k\) 表示;\(k\) 是对应字母的一个映射值。
然后就是常规区间DP三重循环。

但显然,我们在合并区间时还要判断两个区间的名字是否能进一步代替所需名字。
那么可以设 \(vis_{i,j,k}\) 表示字母 \(i\) 和字母 \(j\) 能否代替字母 \(k\)

点击查看代码

posted @ 2023-06-21 19:40  Code_AC  阅读(9)  评论(0编辑  收藏  举报