SHOI2001化工厂装箱员——记忆化搜索

题目:https://www.luogu.org/problemnew/show/P2530

太弱了不会用DP,于是暴搜;

每次传进一个数组c记录当前状态各种物品有多少个,枚举取哪种物品,返回最小值,外加记忆化;

因为各种愚蠢小错误WA了好久。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,c[5],a[105],f[105][15][15][15],inf=100005;
char dc;
int ch(char c)
{
    if(c=='A')return 1;
    if(c=='B')return 2;
    if(c=='C')return 3;
}
//void dfs(int c[],int now,int x)
//{
//    int c1=c[1],c2=c[2],c3=c[3];
////    if(f[now][c1][c2][c3])return;
////    cout<<c1<<c2<<c3;
////    cout<<x<<endl;
//    if(!c1&&!c2&&!c3)
//    {
//        ans=min(ans,x);
//        return;
//    }
//    int j;
//    for(int i=1;i<=3;i++)
//    {
//        if(!c[i])continue;//!
//        int k=c[i];
//        c[i]=0;
//        for(j=now+1;j<=now+k&&j<=n;j++)
//            c[a[j]]++;
//        f[now][c[1]][c[2]][c[3]]=min(f[now][c[1]][c[2]][c[3]],x+1);
//        dfs(c,j,f[now][c[1]][c[2]][c[3]]);
//        c[1]=c1;c[2]=c2;c[3]=c3;
//    }
//}
int dfs(int c[],int now)
{
    if(f[now][c[1]][c[2]][c[3]])return f[now][c[1]][c[2]][c[3]];
    if(!c[1]&&!c[2]&&!c[3])return 0;
    int ans=inf;
    for(int i=1;i<=3;i++)
    {
        if(!c[i])continue;
        int t1=c[1],t2=c[2],t3=c[3],j,t=c[i];
        c[i]=0;
        for(j=now;j<now+t&&j<=n;j++)
            c[a[j]]++;
        ans=min(ans,dfs(c,j));
        c[1]=t1;c[2]=t2;c[3]=t3;
    }
    ans++;//
    f[now][c[1]][c[2]][c[3]]=ans;
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>dc;
        if(dc=='A')a[i]=1;
        if(dc=='B')a[i]=2;
        if(dc=='C')a[i]=3;
    }
    int i;
    for(i=1;i<=10&&i<=n;i++)c[a[i]]++;//
    printf("%d",dfs(c,i));//
    return 0;
}