实用算法实现-第 10 篇 动态规划

10.1 动态规划

10.1.1实例

PKU JudgeOnline, 1160, Post Office.

10.1.2问题描述

一条直线上分布着V个村庄。要在这些村庄中的某些村庄里建一共P个邮局,使得村庄到离它最近的邮局的距离之和最小。输出这个的最小距离之和。

10.1.3输入

105

12 3 6 7 9 11 22 44 50

10.1.4输出

9

10.1.5分析

思路:用opt[i][j]记录把前i个邮局建到前j个村庄中的最优解,用cost[i][j]记录所有在i到j村庄中,建1个邮局的最小代价。显然邮局应该设到中点。让前i个邮局覆盖前j个村庄,第i+1个邮局覆盖第j+1至j+k个村庄(j+k<=n),则状态转移方程为:

opt[i+1][j+k]=min{opt[i][j]+cost[j+1][j+k];} (k+j<=n)

Cost数组存放从i到j中有一个邮局的最小代价,显然该邮局应该放在中间。

Opt[i][j] 表示前i个邮局覆盖前j个村庄的最小代价,对于i=1来说,opt[i][j] = cost[i][j],让前2个邮局覆盖前j个村庄,也就是i=2的情况,可能是一下情况的最优解:第一个邮局覆盖第一个村庄,第二个村庄覆盖2-j个村庄,或者第一个邮局覆盖第1-2个村庄,第二个村庄覆盖3-j个村庄,第一个邮局覆盖第1-3个村庄,第二个村庄覆盖4-j个村庄,等等等等。

10.1.6程序

#include <iostream.h> #include <string.h> int distance[303]; int cost[303][303]; int opt[303][303]; int main() { int V,P; int i; int j; int k; int mid; while(cin>> V){ cin >> P; for(i =1; i <= V; i++){ cin >> distance[i]; } memset(cost, 0, sizeof(cost)); for(i =1; i <= V; i++){ for(j= i; j <= V; j++){ cost[i][j] = 0; mid = (i + j)/2; for(k= i; k <= j; k++){ inttemp = distance[mid] - distance[k]; if(temp< 0){ temp = -temp; } cost[i][j] += temp; } } } memset(opt, 0x7F, sizeof(opt)); opt[0][0] = 0; for(i =0; i <= P; i++){ for(j= i; j <= V; j++){ if(opt[i][j] < 0x7F7F7F7F){ for(k= j; k <= V; k++){ int temp = opt[i][j] + cost[j + 1][k]; if(opt[i+1][k] > temp){ opt[i+1][k] =temp; } } } } } cout << opt[P][V] << endl; } return 1; }

10.2 最长公共子序列(LCS)

LCS问题在《算法导论》中有着详尽的分析。

需要注意的是一个串的LCS并不是唯一的。

10.2.1实例

PKU JudgeOnline, 1458, Common Subsequence.

10.2.2问题描述

给定两个字符串,求两者的最长公共子序列的长度。

10.2.3输入

abcfbc abfcab

programming contest

abcd mnp

10.2.4输出

4

2

0

10.2.5分析

这是基本的LCS问题。问题并不复杂,因为这里不需要构造一个LCS,而只需求出LCS的长度。

10.2.6程序

#include <iostream> #include <string.h> using namespace std; int C[1000][1000]; charX[10000]; charY[10000]; int main() { while(cin>>X>>Y) { int m =strlen(X), n = strlen(Y); int i =0; for(i=0;i<m;i++)C[i][0] = 0; for(i=0;i<n;i++)C[0][i] = 0; for(i=0;i<m;i++) { for(int j=0;j<n;j++) { if(X[i] == Y[j]) { C[i][j] = C[i-1][j-1] +1; } elseif (C[i-1][j] >= C[i][j-1]) { C[i][j] = C[i-1][j]; } else { C[i][j] = C[i][j-1]; } } } cout << C[m-1][n-1] <<endl; } return 1; }
10.3 实例

PKU JudgeOnline, 1160, Post Office.

PKU JudgeOnline, 1014, Dividing.

PKU JudgeOnline, 1157, LITTLE SHOP OFFLOWERS.

PKU JudgeOnline, 3356, AGTC.

PKU JudgeOnline, 1080, Human GeneFunctions.

PKU JudgeOnline, 2250, Compromise.

PKU JudgeOnline, 1458, Common Subsequence.

本文章欢迎转载,请保留原始博客链接http://blog.csdn.net/fsdev/article
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值