Training Plan——动态规划

题目描述:
小Q同学为了准备今年的ICPC Regional,计划在m天之内刷掉n道题,每道题有一个难度值,其中第i道题的难度值为a[i]。
然而处于半颓废状态中的小Q同学不希望在同一天中做难度差距悬殊的题目,定义第i天中刷的题的难度的最大值减最小值为d[i](如果第i天没有刷题,则d[i]=0),那么整个计划的难度为(每天的d[i]2 相加)。
小Q同学可以按照任意的顺序刷题,并且一天中可以刷任意多道题,但是每道题只需要做一次,现在小Q同学想知道完成这个计划的总难度的最小值是多少。
输入描述:

第一行是一个正整数T(≤ 10),表示测试数据的组数,
对于每组测试数据,
第一行是两个整数n(1≤ n ≤ 500)和m(1≤ m ≤ 500),表示题数和天数,
第二行是n个整数a[i](0≤ a[i]≤ 1000000),表示每道题的难度值。

输出描述:

对于每组测试数据,输出一个整数,表示整个计划的最小难度。

输入

2
3 3
1 2 3
3 2
1 2 3

输出

0
1

说明

对于第一组样例,最优方案是一天刷一题。
对于第二组样例,一个最优方案是第一天刷难度值为1和2的题,第二天刷难度值为3的题。

#include<bits/stdc++.h>
using namespace std;
long long a[505];
long long dp[505][505];
int main()
{
    int t,n,m;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        memset(dp,0x3f3f3f3f,sizeof(dp));
        for(int i=1;i<=n;i++)cin>>a[i];
        dp[0][0]=0;
        sort(a+1,a+1+n);
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                for(int k=j;k<=n;k++)
                    dp[i][k]=min(dp[i][k],dp[i-1][j-1]+(a[k]-a[j])*(a[k]-a[j]));
        cout<<dp[m][n]<<endl;
    }
    return 0;
}

这道题一开始想了很久没想出什么好方法,最后看了一眼题解感觉也太简洁了吧!而且看了很久的题解才了解其中的意思 太难了!

分析: 1.dp[i][j] 的意思是 第i天做到第j题的最小值
2. 3个for循环分别意思 i表示第i天 j表示从第几题开始做 k表示做到第几题(j,k区间就是第i天做的题,默认j前就是前面几天做的)
3.最难理解的就是dp[i][k]=min(dp[i][k],dp[i-1][j-1]+(a[k]-a[j])*(a[k]-a[j])); 最后给出一张图作为理解 我们以dp[3][3]为例 第三天做到第三题,可以分别从1,2,3题开始做 所以就需要前一天的数据 然后分别找出最小值即可。

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗吧!骚年!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值