简单$dp$。
$dp[i][j][k]$表示:前$i$个位置染完色,第$i$个位置染的是$j$这种颜色,前$i$个位置分成了$k$组的最小花费。总复杂度$O({n^4})$。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-8; LL INF=1e17; LL dp[110][110][110]; LL p[110][110]; int c[110],n,m,k; int main() { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) scanf("%d",&c[i]); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%lld",&p[i][j]); for(int i=0;i<=n;i++) { for(int j=0;j<=m;j++) { for(int s=0;s<=k;s++) { dp[i][j][s]=INF; } } } if(c[1]!=0) dp[1][c[1]][1]=0; else { for(int j=1;j<=m;j++) dp[1][j][1]=p[1][j]; } for(int i=2;i<=n;i++) { if(c[i]==0) { for(int j=1;j<=m;j++) { for(int s=1;s<=i;s++) { LL tmp=INF; tmp=min(tmp,dp[i-1][j][s]); for(int t=1;t<=m;t++) { if(t==j) continue; tmp=min(tmp,dp[i-1][t][s-1]); } if(tmp==INF) continue; else dp[i][j][s]=tmp+p[i][j]; } } } else { for(int s=1;s<=i;s++) { LL tmp=INF; tmp=min(tmp,dp[i-1][c[i]][s]); for(int t=1;t<=m;t++) { if(t==c[i]) continue; tmp=min(tmp,dp[i-1][t][s-1]); } if(tmp==INF) continue; dp[i][c[i]][s]=tmp; } } } LL ans=INF; for(int j=1;j<=m;j++) ans=min(ans,dp[n][j][k]); if(ans==INF) printf("-1 "); else printf("%lld ",ans); return 0; }