标签:i++ contest ati ios ica blank esc 意思 first
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3392
2 3 1.5 2.0 1.5 1.7 2.0 0 0
0.000000
(1):要求最佳匹配。首先得将两数组从小到大排序~
(2): 然后再明白dp[][]表示的意思;dp[i][j] 表示a数组中前i个数和b数组中前j个数匹配的最优解
(3):接下来 看看状态转移方程; if(i==j)dp[i][j]=dp[i-1][j-1]+fabs(a[i]-b[j]);
else dp[i][j]=min(dp[i-1][j-1]+fabs(a[i]-b[i]),dp[i][j-1]);
(4): 由于题目中的n最大取到10000。假设开个数组dp[10000][10000],那么执行不了~那么再观察观察状态转移方程,发现当前这个数是由它左边这列递推过来的。我们能够用一个dp[2][10000]的滚动数组就可以,由于我仅仅关心最后一个dp[n][m]值,所曾经面的一些值被覆盖不影响我后面的求值过程;(能够在纸上画一画,就知道这个滚动数组了)
#include <iostream> #include <stdio.h> #include <string.h> #include <string> #include <cstdio> #include <algorithm> #include <cmath> const int maxn=11000; using namespace std; double a[maxn],b[maxn]; double dp[2][maxn]; int main() { int n,m; while(cin>>n>>m) { if(n==0&&m==0)break; for(int i=1;i<=n;i++)scanf("%lf",&a[i]); for(int i=1;i<=m;i++)scanf("%lf",&b[i]); double *A=a,*B=b; if(n>m){swap(n,m);swap(A,B);} sort(A+1,A+1+n); sort(B+1,B+1+m); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) for(int j=i;j<=i+m-n;j++) { if(i==j) { dp[i&1][j]=dp[(i-1)&1][j-1]+fabs(A[i]-B[j]); //printf("dp[%d][%d] :%.6lf",i,j,dp[i&1][j]); } else { dp[i&1][j]=min(dp[(i-1)&1][j-1]+fabs(A[i]-B[j]),dp[i&1][j-1]); //printf("dp[%d][%d] :%.6lf",i,j,dp[i&1][j]); } } printf("%.6lf\n",dp[n&1][m]); } return 0; }
标签:i++ contest ati ios ica blank esc 意思 first
原文地址:http://www.cnblogs.com/mfmdaoyou/p/6772482.html