[SHOI2001]化工厂装箱员(dp?暴力:暴力)

��118号工厂是世界唯一秘密提炼锎的化工厂,由于提炼锎的难度非常高,技术不是十分完善,所以工厂生产的锎成品可能会有3种不同的纯度,A:100%,B:1%,C:0.01%,为了出售方便,必须把不同纯度的成品分开装箱,装箱员grant第1次顺序从流水线上取10个成品(如果一共不足10个,则全部取出),以后每一次把手中某种纯度的成品放进相应的箱子,然后再从流水线上顺序取一些成品,使手中保持10个成品(如果把剩下的全部取出不足10个,则全部取出),如果所有的成品都装进了箱子,那么grant的任务就完成了。

��由于装箱是件非常累的事情,grant希望他能够以最少的装箱次数来完成他的任务,现在他请你编个程序帮助他。

Solution

写的像个dp似的,感觉其实就是个暴力(考场这么写肯定是打暴力

设dp[i][j][k][l]表示拿到了i个,A有j个,B有j个,C有k个。

大力转移。

注意特判n<10的情况。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[102][11][11][11],sum[3][104],a[102],n;
inline void mi(int &a,int b){if(b<a)a=b;}
char s[2];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%s",s);
        a[i]=s[0]-'A';
        sum[a[i]][i]=sum[a[i]][i-1]+1;
        for(int j=0;j<=2;++j)if(j!=a[i])sum[j][i]=sum[j][i-1];
    }
    memset(dp,0x3f,sizeof(dp));
    if(n<10){
        cout<<(sum[0][n]!=0)+(sum[1][n]!=0)+(sum[2][n]!=0)<<endl;
        return 0;
    }
    dp[10][sum[0][10]][sum[1][10]][sum[2][10]]=0;
    for(int i=10;i<=n;++i)
      for(int j=0;j<=10;++j)
        for(int k=0;k<=10&&k+j<=10;++k)
          for(int l=0;l<=10&&k+j+l<=10;++l)if(dp[i][j][k][l]!=0x3f3f3f3f){
               if(j){
                   int num=j;
                 mi(dp[min(i+num,n)][sum[0][min(n,i+num)]-sum[0][i]][k+sum[1][min(i+num,n)]-sum[1][i]][l+sum[2][min(i+num,n)]-sum[2][i]],dp[i][j][k][l]+1);
             }
            if(k){
                int num=k;
                mi(dp[min(i+num,n)][j+sum[0][min(n,i+num)]-sum[0][i]][sum[1][min(n,i+num)]-sum[1][i]][l+sum[2][min(n,i+num)]-sum[2][i]],dp[i][j][k][l]+1);
            }
            if(l){
                int num=l;
                mi(dp[min(i+num,n)][j+sum[0][min(i+num,n)]-sum[0][i]][k+sum[1][min(i+num,n)]-sum[1][i]][sum[2][min(i+num,n)]-sum[2][i]],dp[i][j][k][l]+1);
            }
          }
        int ans=0x3f3f3f3f;
    for(int i=0;i<=10;++i)
      for(int j=0;i+j<=10;++j)
        for(int k=0;i+j+k<=10;++k)if(dp[n][i][j][k]!=0x3f3f3f3f)
          ans=min(ans,dp[n][i][j][k]+(i!=0)+(j!=0)+(k!=0));
    cout<<ans;;
    return 0;
}
原文地址:https://www.cnblogs.com/ZH-comld/p/9657522.html