解题:SHOI2001 化工厂装箱员

题面

题外话:从零开始的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 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9677637.html