FZU 1005 Fast Food(dp)
2016-04-20 19:55
344 查看
题意:输入n,k,然后输入n个数,这n个数表示距离起点的距离,现在要选取k个点,使得距离和最小。
分析:我们求的是从n个点中选取k个点使得距离最小,即dp
[k],那么dp
[k]为dp[n-1][k-1]+sum
,dp[n-2][k-1]+sum[n-1]
,dp[n-3][k-1]+sum[n-2]
....dp[1][k-1]+sum[2]
之间的最小值。
其中sum[x][y]表示从x点到y点在此区间选取一个点的最短距离(如果是个数是单数的话,选取中间那个点,偶数的话选取中间两个哪个都行)
记忆化搜索:
dp
分析:我们求的是从n个点中选取k个点使得距离最小,即dp
[k],那么dp
[k]为dp[n-1][k-1]+sum
,dp[n-2][k-1]+sum[n-1]
,dp[n-3][k-1]+sum[n-2]
....dp[1][k-1]+sum[2]
之间的最小值。
其中sum[x][y]表示从x点到y点在此区间选取一个点的最短距离(如果是个数是单数的话,选取中间那个点,偶数的话选取中间两个哪个都行)
记忆化搜索:
#include <iostream> #include <queue> #include <cstdio> #include <cstring> #include <cstdlib> #include <stack> using namespace std; const int oo = 1e9; int a[222]; int dp[222][33]; int sum[222][222]; int DFS(int n, int k) { if(n<0||k<0) return oo; if(dp [k]!=-1) return dp [k]; if(k>=n) { dp [k] = 0; return 0; } dp [k] = oo; for(int i=1; i<=n; i++) { dp [k] = min(dp [k], DFS(i-1, k-1)+sum[i] );//为前n个点建立k个点,可以由前1到n-1个点建立k-1个点推得,找到最优解。 } return dp [k]; } int main() { int n, m; int kk = 1; while(scanf("%d%d", &n, &m), n+m) { a[0] = 0; for(int i=1; i<=n; i++) { scanf("%d", &a[i]); } for(int i=1; i<=n; i++) { sum[i][i] = 0; for(int j=i+1; j<=n; j++) { sum[i][j] = sum[i][j-1]+a[j]-a[(i+j)/2];//sum[i][j]表示在i,j之间选取一个点,消耗的最短距离(如果是单数的话,选取中间那个点,偶数的话选取中间两个哪个都行) } } memset(dp, -1, sizeof(dp)); int ans = DFS(n, m); printf("Chain %d\n", kk++); printf("Total distance sum = %d\n\n", ans); } return 0; }
dp
#include <iostream> #include <queue> #include <cstdio> #include <cstring> #include <cstdlib> #include <stack> using namespace std; const int oo = 1e9; int a[222]; int dp[222][33]; int sum[222][222]; int main() { int n, m; int kk = 1; while(scanf("%d%d", &n, &m), n+m) { a[0] = 0; for(int i=1; i<=n; i++) { scanf("%d", &a[i]); } for(int i=1; i<=n; i++) { sum[i][i] = 0; for(int j=i+1; j<=n; j++) { sum[i][j] = sum[i][j-1]+a[j]-a[(i+j)/2]; } } for(int i=0; i<=n; i++) { for(int j=0; j<=m; j++) { dp[i][j] = oo; } } dp[0][0] = 0; for(int i=1; i<=n; i++) { for(int k=1; k<=m; k++) { for(int j=0; j<i; j++)//此层循环和上层循环哪个在外面都可以,因为dp[i][k]只和 dp[1][k-1]到dp[i-1][k-1]之间的有关 { dp[i][k] = min(dp[i][k], dp[j][k-1]+sum[j+1][i]);//枚举从1到i-1之间的状态,进行更新dp[i][k]的值 } } } printf("Chain %d\n", kk++); printf("Total distance sum = %d\n\n", dp [m]); } return 0; }
相关文章推荐
- 【Unity】第5章 3D坐标系和天空盒
- 268-m-Missing Number
- 第七周项目2-友元类
- 【bzoj4542】[Hnoi2016]大数 莫队
- java序列化(Serializable)的作用和反序列化
- Leetcode——binary-tree-maximum-path-sum
- 如何利用代码标注 MATLAB 图像上的某些点
- 操作系统开发系列—12.e.Makefile
- MapKit框架学习MKCircle 和MKCircleView
- 关于Java静态代码块、初始化块、构造函数的调用顺寻问题?
- Xcode在调试时查看到变量都是nil的问题
- 利用PHP的GD2图像函数 + mysql实现的一个简单的投票系统
- HDU-1020-Encoding,题意不清,其实很水~~
- 第八周
- zzuli 1877 蛤玮打扫教室
- 美团外卖app可行性分析
- 【Unity】6.8 Quaternion类(四元数)
- leecode Nim Game
- 数据总线和地址总线
- 在一个没有大神的公司如何成长