poj3666
#include <iostream> #include <stdio.h> #include <algorithm> #include <cmath> #include <math.h> #include <map> #include <string.h> #define ll long long using namespace std; int n,a[2001],f[2001][2001],b[2001]; inline int read() { char c=getchar();int a=0,b=1; for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1; for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b; } map<int,int> m; int tot,ans=2147483647; int main() { n=read(); for(int i=1;i<=n;i++) { a[i]=read(); b[i]=a[i]; } sort(b+1,b+1+n); memset(f,0x3f,sizeof(f)); for(int i=1;i<=n;i++) { m[b[i]]=++tot; } for(int i=1;i<=tot;i++)f[1][i]=abs(a[1]-b[i]); for(int i=2;i<=n;i++)//单调递增的 { int temp=2147483647; for(int j=1;j<=tot;j++)//只有这两种情况 { temp=min(temp,f[i-1][j]); f[i][j]=min(f[i][j],temp+abs(b[j]-a[i])); } } for(int i=1;i<=tot;i++) { ans=min(ans,f[n][i]); } for(int i=1;i<=tot;i++)f[1][i]=abs(a[1]-b[i]); memset(f,0x3f,sizeof(f)); for(int i=2;i<=n;i++)//单调递减的 { int temp=2147483647; for(int j=tot;j>=1;j--) { temp=min(temp,f[i-1][j]); f[i][j]=min(f[i][j],temp+abs(b[j]-a[i])); } } for(int i=1;i<=tot;i++) { ans=min(ans,f[n][i]); } cout<<ans<<endl; return 0; } /* 只考虑了与前面的数字和现在的数字相等的情况 很明显有误 但是我为什么想了这么久? 1.没有判断清楚转移的状态是从哪里过来的 2.dp其实是一个搜索,所以要把所有可能的东西都考虑进去,其实就是转移的范围,这个和前面一点其实是一样的 总之就是对dp的理解不够深,还有就是题目的特征也没有完全理解 3.没有发现最优子结构 而且加权是在提升至一个值后与这个位置的值进行比较的,但是我却认为这个是发生在提升的过程,是和提升前的值进行比较,也就是题意没有理解清楚 这题目主要就是我题意没有理解清楚,导致一系列的问题 状态的设计一定要保证之后可能优秀的情况不会因为一时的劣势而被覆盖 否则dp的正确性就不被保证了 */