题目链接
错解:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; typedef long long LL; const int N=2007; int a[N]; int m[N][N]; // dp[i][j] 状态结尾的值 LL dp[N][N];// 前i个元素有序最大值小于等于a[j]的最值 int n; int main () { while (~scanf ("%d",&n) ) { for (int i=1;i<=n;i++) scanf ("%d",&a[i]); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { m[i][j]=a[i]; if (a[i]>a[j]) m[i][j]=a[j]; if (a[i]<m[i-1][j]) m[i][j]=m[i-1][j]; dp[i][j]=dp[i-1][j]+abs (a[i]-m[i][j]); cout<<"i: "<<i<<" j: "<<a[j]<<" "<<dp[i][j]<<endl; } LL ans=dp[n][1]; for (int i=1;i<=n;i++) ans=min (ans,dp[n][i]); printf("%lld\n",ans); } return 0; } /* 错误的例子2 5 2 2 10 因为定义的状态是 前n个元素小于等于a[j]的最小次数 dp[3][2](小于等于5)最优解有 2 5 5 和 2 2 2 这两个状态不能合并因为对后面的影响是不一样的 应该重新定义状态 dp[i][j]: 前n个元素有序最大元素是a[j]的最优解 */
正解:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; typedef long long LL; const int N=2007; int a[N],b[N]; LL dp[N][N]; //前i个元素以a[j]结尾的最值 int n; int main () { while (~scanf ("%d",&n)) { memset (dp,0x3f,sizeof(dp)); for (int i=1;i<=n;i++) { scanf ("%d",&a[i]); b[i]=a[i]; } sort (b+1,b+1+n); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { dp[i][j]=abs(a[i]-b[j]); if (i!=1) dp[i][j]+=dp[i-1][j]; dp[i][j]=min (dp[i][j-1],dp[i][j]); } printf("%d\n",dp[n][n]); } return 0; }
对于动态规划的理解我还需要加强。。。
抓住青春的尾巴。。。