Vijos P1323 化工厂装箱员(SHOI2001)题解

【问题描述】
118号工厂是世界唯一秘密提炼锎的化工厂,由于提炼锎的难度非常高,技术不是十分完善,所以工厂生产的锎成品可能会有3种不同的纯度,A:100%,B:1%,C:0.01%,为了出售方便,必须把不同纯度的成品分开装箱,装箱员grant第1次顺序从流水线上取10个成品(如果一共不足10个,则全部取出),以后每一次把手中某种纯度的成品放进相应的箱子,然后再从流水线上顺序取一些成品,使手中保持10个成品(如果把剩下的全部取出不足10个,则全部取出),如果所有的成品都装进了箱子,那么grant的任务就完成了。
    由于装箱是件非常累的事情,grant希望他能够以最少的装箱次数来完成他的任务,现在他请你编个程序帮助他。
【输入格式】
第1行为n(1<=n<=100),为成品的数量
以后n行,每行为一个大写字母A,B或C,表示成品的纯度。
【输出格式】
  仅一行,为grant需要的最少的装箱次数。
【输入样例】worker.in
11
A
B
C
A
B
C
A
B
C
A
B
【输出样例】worker.out
3

嘛,其实就是个DP。
如题,显然,每次装箱,不管是装A or B or C,都是把手上的该类物品全部装箱。
那么,我们可以以此为依据,进行DP。
用四维数组(对,你没看错!)来记录当前状况:f[i][j][k][l]
i:当前为第几个物品
j:当前A的数目
k:当前B的数目
l:当前C的数目
依次枚举j or k or l 变为0的情况。
附上AC程序,可能不比网上其他的好,但可读性高。

#include <vector>
#include <list>
#include <limits.h>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <memory.h>
using namespace std;
//头文件请忽略,要用到的不多,只是个模板而已,懒的每次打程序都要打头文件
int n,f[150][11][11][11],g[150][11][11][11],data[150];

int dp(int k,int a,int b,int c)
{
    int temp;
    temp = a + b + c;
    for (int i = 1; i <= 10 - temp; ++ i)
    {
        ++ k;
        if (k > n) 
            break;
        if (data[k] == 1) 
            ++ a;
        if (data[k] == 2) 
            ++ b;
        if (data[k] == 3) 
            ++ c;
    }
    if (k >= n) 
    {
        g[n][a][b][c] = 1;
        f[n][a][b][c]= int(a>0) + int(b>0) + int(c>0);
        return f[n][a][b][c];
    }
    if (!g[k][a][b][c])
    {
        g[k][a][b][c] = 1;
        f[k][a][b][c] = 100000;
        if (a>0) 
            f[k][a][b][c] = min(f[k][a][b][c],dp(k,0,b,c)+1);
        if (b>0) 
            f[k][a][b][c] = min(f[k][a][b][c],dp(k,a,0,c)+1);
        if (c>0) 
            f[k][a][b][c] = min(f[k][a][b][c],dp(k,a,b,0)+1);
    }
    return f[k][a][b][c];
}


int main()
{
    scanf("%d",&n);
    char c;
    getchar();
    for (int i = 1; i <= n; ++ i)
    {
        scanf("%c",&c);
        getchar();//getchar()用来清空缓存区,防止读入回车……
        data[i]=c - 64;
    } 
    int ans=dp(0,0,0,0);
    printf("%d",ans);
    return 0;
}

最后,请收藏左侧两位大神,以后定然有帮助的哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值