题外话:从零开始的DP学习系列之壹(我真的不是在装弱,我DP真的就这么烂TAT)
从lyd那里学到了一点DP的小技巧,在设状态时可以先假装自己在做搜索,往一个函数里传了一些参数,然后把这些参数抓出来放在状态里就好了=。=
设$dp[i][j][k][h]$表示处理完前$i$个物品,$A$还剩下$j$个,$B$还剩下$k$个,$C$还剩下$h$个的最小次数,然后枚举三种产品的数量,在三个加起来不超过$10$的情况下转移。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=110,M=11; 6 int dp[N][M][M][M],n,x; 7 int main () 8 { 9 scanf("%d",&n); 10 memset(dp,0x3f,sizeof dp); 11 dp[0][0][0][0]=0; char rd[2]; 12 for(int i=1;i<=n;i++) 13 { 14 scanf("%s",rd); 15 for(int j=0;j<=10;j++) 16 for(int k=0;j+k<=10;k++) 17 for(int h=0;j+k+h<=10;h++) 18 { 19 if(rd[0]=='A'&&j) dp[i][j][k][h]=dp[i-1][j-1][k][h]; 20 if(rd[0]=='B'&&k) dp[i][j][k][h]=dp[i-1][j][k-1][h]; 21 if(rd[0]=='C'&&h) dp[i][j][k][h]=dp[i-1][j][k][h-1]; 22 int noww=dp[i][j][k][h]+1; 23 dp[i][0][k][h]=min(dp[i][0][k][h],noww); 24 dp[i][j][0][h]=min(dp[i][j][0][h],noww); 25 dp[i][j][k][0]=min(dp[i][j][k][0],noww); 26 } 27 } 28 printf("%d",dp[n][0][0][0]); 29 return 0; 30 }