题目分析
一道dp的题目,状态很好定义,dp[i][j][k]表示第i个位置为颜色j并且此时树的beauty为k需要的最少的颜料,但是在写状态转移方程的时候我发现自己用了4重循环,我以为这道题会超时,于是没敢下手,但是自己也想不出来优化,于是自己看了一下别人的代码,发现4重循环可以过,于是自己就写了一下,注意状态转移方程,还有状态的初始化问题。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 105;
const LL INF = 0x3f3f3f3f3f3f;
LL color[maxn], maze[maxn][maxn], dp[maxn][maxn][maxn];
int main(){
#ifdef LOCAL
freopen("input.txt", "r", stdin);
#endif // LOCAL
int n,m,k;
while(scanf("%d%d%d", &n, &m, &k) != EOF){
for(int i = 1; i <= n; i++) scanf("%I64d", &color[i]);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
scanf("%I64d", &maze[i][j]);
memset(dp, INF, sizeof(dp));
if(color[1]) dp[1][color[1]][1] = 0;
else{
for(int i = 1; i <= m; i++)
dp[1][i][1] = maze[1][i];
}
for(int i = 2; i <= n; i++){
for(int j = 1; j <= m; j++){
for(int a = 1; a <= k; a++){
if(color[i]){
if(color[i] != j) break;
for(int b = 1; b <= m; b++){
if(b != j)
dp[i][j][a] = min(dp[i][j][a], dp[i-1][b][a-1]);
else
dp[i][j][a] = min(dp[i][j][a], dp[i-1][b][a]);
}
}
else{
for(int b = 1; b <= m; b++){
if(b != j)
dp[i][j][a] = min(dp[i][j][a], dp[i-1][b][a-1] + maze[i][j]);
else
dp[i][j][a] = min(dp[i][j][a], dp[i-1][b][a] + maze[i][j]);
}
}
}
}
}
LL ans = INF;
for(int i = 1; i <= m; i++)
ans = min(ans, dp[n][i][k]);
if(ans == INF) printf("-1\n");
else printf("%I64d\n", ans);
}
return 0;
}