和谐宿舍

 dfs暴力搜:

#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <string.h> 
#include <algorithm>
using namespace std;

int n,m;
int ans=99999999,num=0;
bool vis[105];
int dp[105][105],aa[105];
void dfs(int x,int y,int sum){
    //cout<<x<<" "<<y<<" "<<sum<<" "<<ans<<endl;
    if(x>n){                      //遍历到数组结束 退出 
        ans=min(ans,sum);
    }
    else if(y>=m){                //用了 m 个板子后就退出 
        return;
    }
    for(int i=x;i<=n;i++){        //搜索的过程就是,选定[x,i]的闭区间,找到里面的最大值作为天花板
        int t=-1;                 //然后把面积算出来加上去,然后dfs(i+1,y-1,sum+(面积) )就可以了
        for(int j=x;j<=i;j++){
            t=max(t,aa[j]);      
        }
        dfs(i+1,y+1,sum+t*(i-x+1));
    }
}
int main() {
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>aa[i];
    }
    dfs(1,0,0);
    cout<<ans;
    return 0;
}

 dp解法:

#include <bits/stdc++.h>
using namespace std;

const int ix=1e9;
int n,m;
int h[105],dp[105][105],mx[105][105]; 
//dp[n][m] n表示作品数量 m表示使用木板量
//dp[i][j]表示到第i个作品,用j个木板的最小面积
//因为m个木板肯定全用完最优,所以答案是dp[n][m]
// dp[i][j]=min(dp[i][j],dp[i-k][j-1]+mx[i-k+1][i]*k);

int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++){
        scanf("%d",&h[i]);
        mx[i][i]=h[i];
    }
    //预处理 预先获得mx[i][j]即h_i~h_j的最大值
    for(int i = 1;i <= n;i++){
        for(int j = i+1;j <= n;j++){
            mx[i][j]=max(h[j],mx[i][j-1]);
        }
    }

    for(int i = 1;i <= n;i++){
        dp[i][1] = i*mx[1][i];
        for(int j = 2;j <= m&&j <= i;j++){
            dp[i][j]=ix;
            for(int k = 1;k <= 1+i-j;k++){
                dp[i][j]=min(dp[i][j],dp[i-k][j-1]+mx[i-k+1][i]*k);
            }
        }
    }
    printf("%d
",dp[n][m]);
    return 0;
}
原文地址:https://www.cnblogs.com/xusi/p/12553526.html