POJ3638 Moogle [DP]
来源:互联网 发布:化学分子式绘制软件 编辑:程序博客网 时间:2024/04/29 22:08
题意:
花了不少时间才读懂。
根据例子说吧,0 9 20 40 ,n=4,m=3,即可以存储3个,但是显然头尾0和40必须存储。
所以还可以存储一个,显然取20,这样可以根据公式退出i=2的这个位置的值是10,和9的误差为1,最后输出误差之和/n的值。
所以第二个例子:
10 4
0 10 19 30 40 90 140 190 202 210
最佳方案是取0 40 190 210 这样可以依照公式推出的序列为0 10 20 30 40 90 140 190 200 210,误差和为3。所以输出3/10=0.3
思路:
1<=i<=n;
1<=j<=m;
用dp [ i ][ j ]表示第 i 个元素放在第 j 个位置的误差。
dp[ i ][ j ]=inf; 初始值。
因为第一个元素和最后一个元素肯定要放在j=1,j=m的位置。
所以最后的输出答案值是dp[ n ][ m ]/n;
而dp [ 1 ][ 1 ]=0;(算是边界条件)
1<=i,j<=n;
用w [ i ][ j ]表示 区间[ i , j ]用公式算出来的误差和。
这个w数组很重要,有这个数组可以将整个算法时间复杂度从O(N^4)改进为O(N^3).
状态转移方程为:
dp[i][j]=min(dp[k][j-1]+w[k][j]) (1<=k<=i-1)
所以时间复杂度为O(N^3)
#include<iostream>#include<vector>#include<algorithm>#define Abs(a) ((a)>0?(a):-(a))#define Mod(a,b) (((a)-1+(b))%(b)+1)using namespace std;const int N=205;const double inf=100000000;int n,m;double dp[N][N];//double w[N][N];//int x[N];void solve(){memset(dp,0,sizeof(dp));memset(w,0,sizeof(w));for(int i=1;i<=n;i++)for(int j=i+2;j<=n;j++){for(int k=i+1;k<=j;k++){double tmp=x[i]+(x[j]-x[i])*(k-i)*1.0/(j-i);w[i][j]+=Abs(tmp-x[k]);}}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){dp[i][j]=inf;}dp[1][1]=0;for(int i=2;i<n;i++)for(int j=2;j<m&&j<=i;j++){for(int k=1;k<=i-1;k++){dp[i][j]=min(dp[i][j],w[k][i]+dp[k][j-1]);}}for(int k=1;k<=n-1;k++)dp[n][m]=min(dp[n][m],w[k][n]+dp[k][m-1]);printf("%.4lf\n",dp[n][m]/n);return;}int main(){int cases;scanf("%d",&cases);while(cases--){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",x+i);}solve();}return 0;}
- POJ3638 Moogle [DP]
- pku3638 Moogle (动态规划)
- POJ 3638 Moogle
- I(1894): Moogle
- dp
- dp
- dp
- 【DP】
- dp
- dp
- DP
- DP
- DP
- DP
- DP
- dp
- DP
- dp
- 利用的 .NET构建的MapReduce系统的构想
- 潘多拉:颠覆传统电台模式的“魔力音乐盒”
- 一些有用的sql语句
- 读书笔记 Effective C++
- eclipse启动时弹出Failed to create the Java Virtual Machine 是怎么回事?怎么解决?
- POJ3638 Moogle [DP]
- 什么样的数据适合存放到第二级缓存中(并以Hibernate阐述缓存)
- 招聘人经验浅谈
- Q+无法启动?启动后立即退出?折腾……
- 中小公司职称与职责
- 2012年项目经理薪资调查报告(完整版)
- uninstall Oracle10g on RHEL5
- 模拟频率与数字频率
- silverlight 学习笔记 (七):Prism的第一个应用