【Luogu】P2530化工厂装箱员(DP)

  题目链接

  不知道做出这道题是我能力的一个提升还是能力的回归。

  DP。设f[i][j][k][l]是已经取了i个产品,现在手里还拿着j件A,k件B,l件C,最小的操作数。

  然后状转方程乱搞啊

  

#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

long long f[102][12][12][12];
int s[5][10200];
long long Max;
long long ans=0x7fffffff;
int main(){
    memset(f,127/3,sizeof(f));    Max=f[0][0][0][0];    f[0][0][0][0]=0;
    int n=read();
    for(int i=1;i<=n;++i){
        char c[10];
        scanf("%s",c+1);
        for(int j=1;j<=3;++j)    s[j][i]=s[j][i-1];
        s[c[1]-'A'+1][i]++;
    }
    for(int i=0;i<=n;++i)
        for(int j=0;j<=10;++j)
            for(int k=0;k+j<=10;++k)
                for(int l=0;l+k+j<=10;++l){
                    if(f[i][j][k][l]==Max)    continue;
                    if(j){
                        int a=s[1][min(i+j,n)]-s[1][i],b=s[2][min(i+j,n)]-s[2][i]+k,c=s[3][min(i+j,n)]-s[3][i]+l;
                        f[min(i+j,n)][a][b][c]=min(f[min(i+j,n)][a][b][c],f[i][j][k][l]+1);
                        //printf("%lld ",f[min(i+j,n)][a][b][c]);
                    }
                    if(k){
                        int a=s[1][min(i+k,n)]-s[1][i]+j,b=s[2][min(i+k,n)]-s[2][i],c=s[3][min(i+k,n)]-s[3][i]+l;
                        f[min(i+k,n)][a][b][c]=min(f[min(i+k,n)][a][b][c],f[i][j][k][l]+1);
                        //printf("%lld ",f[min(i+k,n)][a][b][c]);
                    }
                    if(l){
                        int a=s[1][min(i+l,n)]-s[1][i]+j,b=s[2][min(i+l,n)]-s[2][i]+k,c=s[3][min(i+l,n)]-s[3][i];
                        f[min(i+l,n)][a][b][c]=min(f[min(i+l,n)][a][b][c],f[i][j][k][l]+1);
                        //printf("%lld ",f[min(i+l,n)][a][b][c]);
                    }
                    if(j+k+l<10){
                        int q=10-(j+k+l);
                        int a=s[1][min(i+q,n)]-s[1][i]+j,b=s[2][min(i+q,n)]-s[2][i]+k,c=s[3][min(i+q,n)]-s[3][i]+l;
                        f[min(i+q,n)][a][b][c]=min(f[min(i+q,n)][a][b][c],f[i][j][k][l]);
                    }
                }
    for(int i=0;i<=10;++i)
        for(int j=0;j+i<=10;++j)
            for(int k=0;k+j+i<=10;++k)
                ans=min(ans,f[n][i][j][k]+(i>0?1:0)+(j>0?1:0)+(k>0?1:0));
    printf("%lld",ans);
    return 0;
}

 

posted @ 2017-12-22 17:06  Konoset  阅读(161)  评论(0编辑  收藏  举报