• 【题解】SHOI2001化工厂装箱员


    ————传送:洛谷P2530

    这道题目还是挺简单的,状态也容易想到。

    数据范围非常的小,所以即便是很多维度,复杂度也完全可以接受。定义状态:dp[i][a][b][c]为手上的货物拿到第i个时三种物品分别有a, b, c个所用的最少次数。

    状态转移就暴力枚举是放下a,b,c中的哪一个。

    只不过需要特判一下n<10的情况。//再一次对自己丑陋的代码有点接受无能……

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 102
    #define INF 999999
    int n, ans = INF, suma[maxn], sumb[maxn], sumc[maxn], dp[maxn][11][11][11];
    char c[maxn];
    
    int min(int a, int b)
    {
        if(b == -1) return a;
        if(a == -1) return b;
        return a < b ? a : b;
    }
    
    int trans(int x, int y, int aa, int bb, int cc)
    {
        int a = suma[y] - suma[x], b = sumb[y] - sumb[x], c = sumc[y] - sumc[x];
        int sum = a + b + c + aa + bb + cc;
        bool done = false;
        if(sum - aa <= 10) done = true, dp[y][a][b + bb][c + cc] = min(dp[x][aa][bb][cc] + 1, dp[y][a][b + bb][c + cc]);
        if(sum - bb <= 10) done = true, dp[y][a + aa][b][c + cc] = min(dp[x][aa][bb][cc] + 1, dp[y][a + aa][b][c + cc]);
        if(sum - cc <= 10) done = true, dp[y][a + aa][b + bb][c] = min(dp[x][aa][bb][cc] + 1, dp[y][a + aa][b + bb][c]);
        if(!done) return -1;
        else return 0;
    }
    
    int main()
    {
        scanf("%d
    ", &n);
        memset(dp, -1, sizeof(dp));
        for(int i = 1; i <= n; i ++)
        {
            cin >> c[i];
            suma[i] = suma[i - 1];
            sumb[i] = sumb[i - 1];
            sumc[i] = sumc[i - 1];
            if(c[i] == 'A') suma[i] ++;
            else if(c[i] == 'B') sumb[i] ++;
            else sumc[i] ++;
        }
        if(n < 10)//特判
        {
            ans = 0;
            if(suma[n]) ans ++;
            if(sumb[n]) ans ++;
            if(sumc[n]) ans ++;
            printf("%d
    ", ans);
            return 0;
        }
        dp[10][suma[10]][sumb[10]][sumc[10]] = 0;
        for(int i = 10; i <= n; i ++)
        {
            for(int aa = 0; aa <= 10; aa ++)
                for(int bb = 0; bb <= 10; bb ++)
                    for(int cc = 0; cc <= 10; cc ++)
                    {
                        if(dp[i][aa][bb][cc] == -1) continue;
                        for(int j = i + 1; j <= n; j ++)
                            if(trans(i, j, aa, bb, cc) == -1) break; 
                    }
        }
        for(int aa = 0; aa <= 10; aa ++)
            for(int bb = 0; bb <= 10; bb ++)
                for(int cc = 0; cc <= 10; cc ++)
                {
                    if(dp[n][aa][bb][cc] == -1) continue;
                    int tem = 0;
                    if(aa) tem ++;
                    if(bb) tem ++;
                    if(cc) tem ++;
                    ans = min(ans, dp[n][aa][bb][cc] + tem);
                }
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    解决rsyslog 断电或者被kill 重发问题
    perl dbi 测试 mysql wait_timeout
    PERL DBI 自动重连问题
    elasticsearch 重启后,需要的操作
    Filter Conditions 过滤条件
    rsyslog Properties 属性:
    nginx对比haproxy 的反向代理
    Templates 模板:
    1.Basic Structure
    beego的orm ,用的数据库sqlite3
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/8408696.html
Copyright © 2020-2023  润新知