【codevs2098】【Tyvj1625】化工厂装箱员,煞笔的人打煞笔的DP

传送门1
传送门2
写在前面:数据结构题写多了,写dp反而不会写了
思路:刚开始以为是贪心,很快发现这是错误的233(反例很好找的),后来看到n才100,就动了一些歪脑筋打暴力,后来才发现是一个可以记忆化搜索的DP,f[i][x][y][z]指流水线上剩余i个产品,手里有x个A,y个B,z个C时所需要的最少装箱次数,显然我们可以以此转移三种状态:装箱A,装箱B,装箱C,同时记忆化搜索除去了很多重复的状态(比如在流水线上一堆C的情况下装2个A,3个B与装3个B, 2个A效果一样)
注意:别打暴搜,注意细节!
代码:

#include<bits/stdc++.h>
using namespace std;
int n,a[110],f[110][20][20][20];
char ch;
bool flag[110][20][20][20];
int dfs(int remain,int x,int y,int z)
{
    int tot=x+y+z,k=0;
    for (int i=n-remain+1;i<=n;i++)
    {
        if (tot+k==10) break;
        if (a[i]==1) x++;
        if (a[i]==2) y++;
        if (a[i]==3) z++;
        k++;
    }
    if (flag[remain-k][x][y][z]) return f[remain-k][x][y][z];
    flag[remain-k][x][y][z]=1;
    if (remain-k==0)
    {
        f[0][x][y][z]=min(f[0][x][y][z],(x>0)+(y>0)+(z>0));//没有剩余的情况下显然装a,b,c的顺序就无所谓了,直接加上就好
        return f[0][x][y][z];
    }
    if (x) f[remain-k][x][y][z]=min(f[remain-k][x][y][z],dfs(remain-k,0,y,z)+1);
    if (y) f[remain-k][x][y][z]=min(f[remain-k][x][y][z],dfs(remain-k,x,0,z)+1);
    if (z) f[remain-k][x][y][z]=min(f[remain-k][x][y][z],dfs(remain-k,x,y,0)+1);
    return f[remain-k][x][y][z];
}
main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        ch=getchar();
        while (ch<'A'||ch>'C') ch=getchar();
        a[i]=ch-'A'+1;
    }
    memset(f,63,sizeof(f));
    printf("%d",dfs(n,0,0,0));
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值