51nod 1021 石子归并(基础dp)
2017-05-10 19:21
369 查看
假设有n堆石子,要把石子有次序的两两合并,要求代价最小。假设1~n之间有一k,把石子分为1~k和k~n两部分,划分后的这两部分再继续这样划分,直到不能划分,然后就开始分别合并,求出合并后的最小代价,即cost[1~n]=min{cost[1~k]+cost[k+1~n] | 1<=k<=n },用记忆化搜索还是比较好写的。
用循环写:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 110; int num[MAXN]; int sum[MAXN]; int n; int dp[MAXN][MAXN]; int dfs(int l, int r) { if(dp[l][r] > 0) return dp[l][r]; if(l == r) return dp[l][r] = 0; if(l+1 == r) return dp[l][r] = num[l]+num[r]; dp[l][r] = INF; for(int k = l; k < r; ++k) dp[l][r] = min(dp[l][r],dfs(l,k)+dfs(k+1,r)+sum[r]-sum[l-1]); return dp[l][r]; } int main() { scanf("%d",&n); for(int i = 1; i <= n; ++i) { scanf("%d",&num[i]); sum[i] = sum[i-1]+num[i]; } int res = dfs(1,n); printf("%d\n",res); return 0; }
用循环写:
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 110; int dp[MAXN][MAXN]; int num[MAXN],sum[MAXN]; int n; int main() { cin >> n; for(int i = 1; i <= n; ++i) { cin >> num[i]; sum[i] = sum[i-1]+num[i]; } for(int l = 2; l <= n; ++l) { for(int i = 1; i <= n; ++i) { int j = i+l-1; if(j > n) break; dp[i][j] = INF; for(int k = i; k < j; ++k) dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]); } } cout << dp[1] << endl; return 0; }
相关文章推荐
- 51nod 1021 石子归并 dp
- 51nod 1021 石子归并(区间dp 详细解释)
- 51Nod - 1021 石子归并(经典dp)
- 51Nod - 1021石子归并(区间DP)
- 51Nod - 1021 石子归并 区间DP入门-分析
- 51nod 1021 石子归并(区间dp)
- 【51Nod】1021 - 石子归并(区间dp & 四边形不等式优化)
- 51nod 1021 石子归并(dp-矩阵连乘)
- 经典问题二.【区间dp】石子归并 51nod 1021
- 51nod 1021石子归并 dp
- [DP 四边形不等式优化] 51Nod 1022 石子归并 V2
- 51nod 1021 石子归并
- 1021 石子归并 (区间dp)
- AC日记——石子归并 51nod 1021
- 51nod 1021 石子归并
- 【基础练习】【区间DP】codevs2102 石子归并2(环形)题解
- 51nod 石子归并 (dp)
- 51Nod 1021 石子归并
- 51nod 1021 石子归并
- 1021 石子归并 dp