【题解】平版

文章来源

题目

题目描述

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

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

输入

1 1 1行,两个空格分开的整数, N N N M M M
2 2 2 N + 1 N+1 N+1行,每行一个整数 A i A_i Ai

输出

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

样例输入&输出

输入:

3 6
3
3
1

输出:

5

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

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

数据范围

1 ≤ N ≤ 10 1≤N≤10 1N10

1 ≤ M ≤ 10000 1≤M≤10000 1M10000

1 ≤ A i ≤ 100 1≤A_i≤100 1Ai100

题解

发现 M M M的范围非常小。

于是乎想到dp。

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

d p [ i ] [ j ] = min ⁡ { ( k − A [ j ] ) 2 + d p [ i − k ∗ k ] [ j − 1 ] } dp[i][j] = \min\{(k-A[j])^2 + dp[i-k*k][j-1]\} dp[i][j]=min{(kA[j])2+dp[ikk][j1]}(只考虑换第j块平板)

初始条件: d p [ 0 ] [ 0 ] = 0 , d p [ i > 0 ] [ 0 ] = I N F dp[0][0]=0,dp[i>0][0]=INF dp[0][0]=0,dp[i>0][0]=INF

时间复杂度: O ( N M M ) = 1 0 7 O(NM\sqrt{M})=10^7 O(NMM )=107

代码:

#include
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;
}

你可能感兴趣的:(C++,题解,转载,c++,c#,c语言,其他,经验分享)