【Luogu】P2530化工厂装箱员(DP)
不知道做出这道题是我能力的一个提升还是能力的回归。
DP。设f[i][j][k][l]是已经取了i个产品,现在手里还拿着j件A,k件B,l件C,最小的操作数。
然后状转方程乱搞啊
#include<cstring> #include<cstdlib> #include<cstdio> #include<cctype> #include<algorithm> using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } long long f[102][12][12][12]; int s[5][10200]; long long Max; long long ans=0x7fffffff; int main(){ memset(f,127/3,sizeof(f)); Max=f[0][0][0][0]; f[0][0][0][0]=0; int n=read(); for(int i=1;i<=n;++i){ char c[10]; scanf("%s",c+1); for(int j=1;j<=3;++j) s[j][i]=s[j][i-1]; s[c[1]-'A'+1][i]++; } for(int i=0;i<=n;++i) for(int j=0;j<=10;++j) for(int k=0;k+j<=10;++k) for(int l=0;l+k+j<=10;++l){ if(f[i][j][k][l]==Max) continue; if(j){ int a=s[1][min(i+j,n)]-s[1][i],b=s[2][min(i+j,n)]-s[2][i]+k,c=s[3][min(i+j,n)]-s[3][i]+l; f[min(i+j,n)][a][b][c]=min(f[min(i+j,n)][a][b][c],f[i][j][k][l]+1); //printf("%lld ",f[min(i+j,n)][a][b][c]); } if(k){ int a=s[1][min(i+k,n)]-s[1][i]+j,b=s[2][min(i+k,n)]-s[2][i],c=s[3][min(i+k,n)]-s[3][i]+l; f[min(i+k,n)][a][b][c]=min(f[min(i+k,n)][a][b][c],f[i][j][k][l]+1); //printf("%lld ",f[min(i+k,n)][a][b][c]); } if(l){ int a=s[1][min(i+l,n)]-s[1][i]+j,b=s[2][min(i+l,n)]-s[2][i]+k,c=s[3][min(i+l,n)]-s[3][i]; f[min(i+l,n)][a][b][c]=min(f[min(i+l,n)][a][b][c],f[i][j][k][l]+1); //printf("%lld ",f[min(i+l,n)][a][b][c]); } if(j+k+l<10){ int q=10-(j+k+l); int a=s[1][min(i+q,n)]-s[1][i]+j,b=s[2][min(i+q,n)]-s[2][i]+k,c=s[3][min(i+q,n)]-s[3][i]+l; f[min(i+q,n)][a][b][c]=min(f[min(i+q,n)][a][b][c],f[i][j][k][l]); } } for(int i=0;i<=10;++i) for(int j=0;j+i<=10;++j) for(int k=0;k+j+i<=10;++k) ans=min(ans,f[n][i][j][k]+(i>0?1:0)+(j>0?1:0)+(k>0?1:0)); printf("%lld",ans); return 0; }