code[VS] 1048 石子归并
题目描写叙述 Description
有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子。一次合并的代价为两堆石子的重量和w[i]+w[i+1]。
问安排如何的合并顺序,可以使得总合并代价达到最小。
输入描写叙述 Input Description
第一行一个整数n(n<=100)
第二行n个整数w1,w2...wn (wi <= 100)
输出描写叙述 Output Description
一个整数表示最小合并代价
例子输入 Sample Input
4
4 1 1 4
例子输出 Sample Output
18
以相邻的石头堆来合并,相当于在一个串中割两半,能够用dp[i][j]表示序号从i到j的石头堆合并的最小cost。
dp[i][j]=dp[i][k]+dp[k+1][j]+sum[i][j](i<k<=j)。当中sum[i][j]代表序号i到j石头堆的重量和。我认为理论上搜索和循环都能做,我用的是搜索,写起来简单无脑。
#include <bits/stdc++.h> using namespace std; int vis[102][102]; int n; int stone[102]; void init(){ for(int i=1;i<=102;i++) for(int j=1;j<=102;j++) vis[i][j]=9999999; } int dp(int i,int j){ if(vis[i][j]<9999999) return vis[i][j]; if(j-i==1){ vis[i][j]=stone[i]+stone[j]; return vis[i][j]; } if(i==j){ vis[i][i]=0; return 0; } for(int k=i+1;k<=j;k++){ int sum=0; for(int i1=i;i1<=j;i1++) sum+=stone[i1]; vis[i][j]=min(vis[i][j],dp(i,k-1)+dp(k,j)+sum); } return vis[i][j]; } int main(){ init(); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&stone[i]); } printf("%d\n",dp(1,n)); }
posted on 2017-04-25 16:47 yjbjingcha 阅读(160) 评论(0) 编辑 收藏 举报