状态:f[i][j][k][m] : 前i个物品 当前手中有j个"A" k个"B" m个"C"时的最小卸货次数
很明显对于第i个物品可以
1:)只取出来 暂时不装进去 前提就是当前手中货物数量<10
2:)取出来后 装进去 没有前提
所以转移方程就出来了:
f[i][j][k][m] = f[i-1][j-1][k][m] if(ob[i]=='A' && j)
f[i][j][k][m] = f[i-1][j][k-1][m] if(ob[i]=='B' && k)
f[i][j][k][m] = f[i-1][j][k][m-1] if(ob[i]=='C' && m)
以上三个均是 只取出来
f[i][0][k][m] = f[i][j][k][m] + 1 ;
f[i][j][0][m] = f[i][j][k][m] + 1 ;
f[i][j][k][0] = f[i][j][k][m] + 1 ;
这三个就是卸货啦, 还有一个大前提:j+k+m<=10
初值:f[0][0][0][0]=0 ; 其他均为inf
目标:f[n][0][0][0]
#include<iostream>
#include<cstdio>
#include<bits/stdc++.h>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define maxn 100005
int dp[105][15][15][15],n;
int main()
{
// freopen("chess.in","r",stdin);
// freopen("standard output","w",stdout);
char ch;
cin>>n;
memset(dp,inf,sizeof(dp));
dp[0][0][0][0]=0;
for(int i=1; i<=n; i++)
{
cin>>ch;
for(int a=0; a<=10; a++)
{
for(int b=0; b<=10; b++)
{
for(int c=0; c<=10; c++)
{
if(a+b+c>10)
continue;
if(ch=='A'&&a!=0)
dp[i][a][b][c]=dp[i-1][a-1][b][c];
if(ch=='B'&&b!=0)
dp[i][a][b][c]=dp[i-1][a][b-1][c];
if(ch=='C'&&c!=0)
dp[i][a][b][c]=dp[i-1][a][b][c-1];
dp[i][0][b][c]=min(dp[i][0][b][c],dp[i][a][b][c]+1);
dp[i][a][0][c]=min(dp[i][a][0][c],dp[i][a][b][c]+1);
dp[i][a][b][0]=min(dp[i][a][b][0],dp[i][a][b][c]+1);
}
}
}
}
printf("%d\n",dp[n][0][0][0]);
return 0;
}