和谐宿舍
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\n",dp[n][m]); return 0; }