题目:https://codeforces.com/problemset/problem/711/C
题意:给你n,m,k,代表n个数的序列,有m种颜色可以涂,0代表未涂颜色,其他代表已经涂好了,连着一段是相同颜色的是一个连通块,求正好有k个连通块的最小花费
思路:首先每个位置有可能有m中颜色,而且要满足k个,我们我们可以推出所有情况
dp[n][m][k]
n代表前n个数
m代表当前涂m色
k代表满足k个了
#include<cstdio> #include<cmath> #include<algorithm> #include<map> #include<string> #include<cstring> #include<iostream> #include<vector> #define mod 1000000007 #define maxn 200005 #define INF 100000000000000+10 using namespace std; typedef long long ll; ll n,m,k; ll a[105]; ll c[105][105]; ll dp[105][105][105]; int main() { cin>>n>>m>>k; for(int i=1;i<=n;i++){ cin>>a[i]; } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>c[i][j]; } } for(int i=0;i<=n;i++){ for(int j=0;j<=m;j++){ for(int z=0;z<=k;z++) dp[i][j][z]=INF; } } if(a[1]){ dp[1][a[1]][1]=0; } else{ for(int j=1;j<=m;j++){ dp[1][j][1]=c[1][j]; } } for(int i=2;i<=n;i++) { if(!a[i])//不是0的时候 { for(int j=1;j<=m;j++) for(int k=1;k<=i;k++) for(int h=1;h<=m;h++) { if(j==h) dp[i][j][k]=min(dp[i][j][k],dp[i-1][h][k]+c[i][j]);//颜色相同情况 else dp[i][j][k]=min(dp[i][j][k],dp[i-1][h][k-1]+c[i][j]);//颜色不相同 } } else { for(int k=1;k<=i;k++) for(int h=1;h<=m;h++) { if(a[i]==h) dp[i][a[i]][k]=min(dp[i][a[i]][k],dp[i-1][a[i]][k]);//同上 else dp[i][a[i]][k]=min(dp[i][a[i]][k],dp[i-1][h][k-1]); } } } ll mn=INF; for(int i=1;i<=m;i++){ mn=min(mn,dp[n][i][k]); } if(mn>=INF) printf("-1"); else cout<<mn; }