Andysun06的博客

  • 首页
  • 文章列表 
  • 博客统计
  • 个人中心
Andysun06的博客
  1. 首页
  2. C++语言
  3. 正文

【题解】平版

2021年10月7日 188点热度 1人点赞 2条评论

题目

题目描述

小明喜欢玩拼板游戏,买了N块正方形的拼板,边长分别是A_1,A_2,...A_N。可是在玩拼图游戏的过程中,他发现自己把拼板的尺寸搞错了。所以他需要调换其中的一些,使得调换以后所有拼板总面积正好是M。调换拼板是需要成本的,把一块边长是A_i的拼板替换成一块边长是B_i的拼板需要的成本是(A_i-B_i)^2。特别的,小明只能把之前买的拼板用来做调换。也就是说,他不能用A拼板来调换B拼板,然后再用B拼板来调换C拼板。

请你计算,小明要达到目的所需要花的最小代价。如果无法达到目的,输出-1。

输入

第1行,两个空格分开的整数,N和M。
第2到N+1行,每行一个整数A_i。

输出

一个整数,能通过调换使得总面积达到M的最小代价,如果不可行输出-1。

样例输入&输出

输入:

3 6
3
3
1

输出:

5

样例说明:一共有3块拼板,两块的边长为3,一块的边长为1,想要通过替换使得总面积为6。

把两块边长为3的拼板分别调换为边长为2和边长为1的,总面积变成4+1+1=6,所需要花的代价是4+1=5。

数据范围

1≤N≤10

1≤M≤10000

1≤A_i≤100

题解

发现M的范围非常小。

于是乎想到dp。

dp[i][j]表示只用前j块拼板获得i面积所需要的最小代价,INF表示不可行。转移方程为:

dp[i][j] = \min{(k-A[j])^2 + dp[i-k*k][j-1]}(只考虑换第j块平板)

初始条件:dp[0][0]=0,dp[i>0][0]=INF

时间复杂度:O(NM\sqrt{M})=10^7

代码:

#include<bits/stdc++.h>
using namespace std;
#define INF 1919810114
int n,m;
int a[20];
int dp[10010][20];
int main(){
freopen("slab.in","r",stdin);
freopen("slab.out","w",stdout);

    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=m;i++) dp[i][0]=INF;
    for(int j=1;j<=n;j++)
        for(int i=0;i<=m;i++){
            dp[i][j]=INF;
            for(int k=1;k*k<=i;k++) dp[i][j]=min(dp[i][j],(a[j]-k)*(a[j]-k)+dp[i-k*k][j-1]);
        }
    if(dp[m][n]==INF) cout<<-1;
    else cout<<dp[m][n];
    return 0;
}
本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: C++ 原创 洛谷 题解
最后更新:2021年10月9日

tommysun

这个人很强,什么都没留下

打赏 点赞
< 上一篇

文章评论

  • Andysun06

    完全看不懂,写的啥玩意

    2021年10月7日
    回复
    • tommysun

      @Andysun06 /kk

      2021年10月9日
      回复
  • 取消回复

    COPYRIGHT © 2021 hackingfans.top. ALL RIGHTS RESERVED.

    THEME KRATOS MADE BY VTROIS

    油
    加
    王
    帅