问题 H: 啊冷种树[动态规划]

题目描述

阿冷喜欢种树,但他有个奇怪的爱好,他喜欢将连续相同种类的树当成一片森林。
(比如trees=[0,1,1,2,2,2,1],它包含4片森林,[{0}, {1,1}, {2,2,2}, {1}])

现在有m颗树,有n种树的种类(数的种类从1到n)
并给出在位置i,种植种类为j的树所消耗的力气 cost[i][j]
求阿冷最终将m颗树种植成k片森林的最少消耗的力气。

输入

第一行有一个参数T, 代表有T组样例

接下来一行 有三个参数 m, n, k 代表 m颗树, n种树,以及最终需要的森林数
接下来有m行,每行有n个参数,分别代表在位置i, 种植种类为j的树所消耗的力气。

1 <= T <= 5
1 <= m <= 100
1 <= n <= 10
1 <= k <= m
1 <= cost[i][j] <= 50
 

输出

对于每一个样例,每行输出最少消耗的力气,不存在的情况输出-1
 

样例输入

1
2 2 1
2 5
1 3

样例输出

3

提示

2颗树   2种树 最后需要生成一片森林

第一颗树 种植为种类1 所需要的力气为 2

第一颗树 种植为种类2 所需要的力气为 5

第二颗树 种植为种类1 所需要的力气为 1

第二颗树 种植为种类2 所需要的力气为 3

因而形成一片森林  所需要的最少力气为3  (即将第一棵树和第二颗都种植种类为1的树)

 

题型: 动态规划

#include <bits/stdc++.h>
using namespace std;
 
const int N = 110;
const int M = 15;
int dp[N][M][N]; // dp[i][j][k] ±Ì æ µΩµ⁄iø≈ ˜, ≤¢«“µ⁄iø≈ ˜ π”√µ⁄j÷÷£¨◊Ó∫Û–Œ≥…k∆¨…≠¡÷µƒ◊Ó–°¡¶∆¯
int m, n, k;
int cost[N][N];
const int INF = 0x3f3f3f3f;
 
int main()
{
    // freopen("../../in.txt", "r", stdin);
    int T;
    cin >> T;
    while (T--)
    {
        scanf("%d %d %d", &m, &n, &k);// m颗树, n种树,以及最终需要的森林数
 
        for (int i=1; i<=m; i++)
        {
            for (int j=1; j<=n; j++)
            {
                scanf("%d", &cost[i][j]);
            }
        }//输入代价
 
        memset(dp, 0x3f, sizeof(dp));
        // µ⁄“ªø≈ ˜£¨÷÷¿‡Œ™i, 1∆¨…≠¡÷µƒ¥˙º€ « cost[1][i]
        for (int i=1; i<=n; i++)
        {
            dp[1][i][1] = cost[1][i];
        }
 
        for (int i=2; i<=m; i++)//m棵树
        {
            for (int pre=1; pre<=n; pre++)//位置
            {
                for (int now=1; now<=n; now++)//位置
                {
                    for (int tt=0; tt<=k; tt++)//树种
                    {
                        if (pre == now)//位置pre和now选择的是同一种树,不会增加森林
                        {
                            dp[i][now][tt] = min(dp[i][now][tt], dp[i-1][pre][tt] + cost[i][now]);
                        }
                        else
                        {
                            if (tt > 0)
                                dp[i][now][tt] = min(dp[i][now][tt], dp[i-1][pre][tt-1] + cost[i][now]);
                        }
                    }
                }
            }
        }
        int res = INF;
        for (int i=1; i<=n; i++)
        {
            res = min(res, dp[m][i][k]);
        }
        res = (res >= INF) ? -1 : res;
        cout << res << endl;
    }
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值