・注意事項・
動的なプログラミングの問題は、一般に二つの特徴があります。
①最適な下部
②の重複部分問題
だから、アルゴリズムのデザインのアイデアは突然DPアルゴリズムを使用することができ、問題を考えていない、
しかし、あなたが問題を使用できる場合には、解決分割統治+徹底的に解決することができますすることができ、徹底的な外観にすることはできません。
問題が含まれている場合動的なプログラミングで言葉の問題や最適解を解決されているので、この時間を重ねます。
・ポイントの誘導(個人)・
[1]カードは、多くの場合、問題は次のとおりです。
(1)SQRTは、一度だけ開くことができます
オープン、TLE 6点で私の一番下
(2)精度の問題
ここでSQRT最初のプラス、精度の損失の可能性、ではないが、問題を開けないでください。
(3)出力問題のない丸め
最後に、コード:
#include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> #include<cstring> using namespace std; int n,m; const int N=1003; int sum[N],st[N][N],f[403][N]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&sum[i]),sum[i]= sum[i]*sum[i] + sum[i-1]; //memset(f,0x3f,sizeof(f)); for(int i=1;i<=n;i++) f[1][i]=sum[i]; for(int k=2;k<=m;k++) for(int i=k;i<=n;i++) { f[k][i]=max(f[k-1][k-1],sum[i]-sum[k-1] ); for(int j=k+1;j<=i;j++) f[k][i]=min(f[k][i],max(f[k-1][j-1],sum[i]-sum[j-1] )); } int ans=(double)(sqrt((double)f[m][n]))*100; //printf("%d.%d",ans/100,ans%100);//错误写法:可能丢了1个前导0,最后没有两位小数 printf("%.2lf",ans/100.0); return 0; }
【2】逢低购买
先求最长的长度,以减少dp的复杂度
然后我想的是,记录f[k][i],以min(mx[i],mx[j]+1) * n* n的复杂度dp
但是!!!
可以压维成f[i],他的k是mx[i],并且这样是保证找到所有方案的!!!
直接不tle了
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #define int long long using namespace std; int n; const int N=5003; int d[N],ans; int mx[N],f[N]; int a[N]; void get_mx_time() { int len=0; for(int i=1;i<=n;i++) { int pos=lower_bound(a+1,a+len+1,-d[i])-a; a[pos]=-d[i]; if(pos>len) len++; mx[i]=pos; } ans=len; } signed main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&d[i]); get_mx_time(); printf("%d ",ans); f[1]=1; for(int i=2;i<=n;i++) { if(mx[i]==1) f[i]=1; for(int j=1;j<i;j++) if(d[j]>d[i] && mx[i]==mx[j]+1 ) f[i]+=f[j]; else if(d[j]==d[i] && mx[i]==mx[j] ) f[i]=0; } int tmp=0; for(int i=ans;i<=n;i++) if(mx[i]==ans) tmp+=f[i]; printf("%d\n",tmp); return 0; }
高精度版本稍后放上