zoukankan      html  css  js  c++  java
  • 题解——洛谷P4767 [IOI2000]邮局(区间DP)

    这题是一道区间DP

    思维难度主要集中在如何预处理距离上

    生活经验得,邮局放在中间显然最优

    所以我们可以递推求出( w[i][j] )表示i,j之间放一个邮局得距离

    然后设出状态转移方程

    设( dp[i][j] )表示从1开始到i放j个邮局的最短距离

    然后转移为:( dp[i][j]=min(dp[k][j-1]+w[k+1][j],dp[i][j]),i le k le j )

    显然是个( O(n^{3}) )的DP

    能够得40分

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define int long long
    using namespace std;
    int w[3010][3010],dp[3010][310],n,p,x[3010];
    signed main(){
      scanf("%lld %lld",&n,&p);
      for(int i=1;i<=n;i++)
        scanf("%lld",&x[i]);
      sort(x+1,x+n+1);
      memset(w,0x3f,sizeof(w));
      for(int i=1;i<=n;i++)
        w[i][i]=0;
      for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
          w[i][j]=w[i][j-1]+x[j]-x[(i+j)/2];
      memset(dp,0x3f,sizeof(dp));
      for(int i=1;i<=n;i++)
        dp[i][1]=w[1][i];
      for(int i=1;i<=p;i++)
        dp[i][i]=0;
      for(int i=2;i<=p;i++)
        for(int j=i+1;j<=n;j++)
          for(int k=i-1;k<=j;k++){
            dp[j][i]=min(dp[j][i],dp[k][i-1]+w[k+1][j]);
    //5        printf("%d %d %d %d
    ",i,j,k,dp[j][i]);
          }
      /*for(int l=1;l<=n;l++)
        for(int i=1;i+l<=n;++)
          printf("w[%d][%d]=%d
    ",i,i+l,w[i][i+l]);*/
      printf("%lld
    ",dp[n][p]);
      return 0;
    }

    然后就是优化

    我们可以发现一些显然的性质

    ( w[i^{'}][j] le w[i][j^{'}] , i le i^{'} le j le j^{'} )

    ( w[i][j]+w[i^{'}][j^{'}] le w[i^{'}][j]+w[i][j^{'}] )

    然后就可以用四边形不等式优化DP了!

    然后QwQ

    复杂度( O(n^{2}) )

    没了

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define int long long
    using namespace std;
    int w[3010][3010],dp[3010][310],n,p,x[3010],s[3010][310];
    signed main(){
      scanf("%lld %lld",&n,&p);
      for(int i=1;i<=n;i++)
        scanf("%lld",&x[i]);
      sort(x+1,x+n+1);
      memset(w,0x3f,sizeof(w));
      for(int i=1;i<=n;i++)
        w[i][i]=0;
      for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
          w[i][j]=w[i][j-1]+x[j]-x[(i+j)/2];
      memset(dp,0x3f,sizeof(dp));
      for(int i=1;i<=n;i++)
        dp[i][1]=w[1][i],s[i][1]=0;;
      for(int i=1;i<=p;i++)
        dp[i][i]=0;
      for(int i=2;i<=p;i++){
        s[n+1][i]=n;
        for(int j=n;j>=i+1;j--)
          for(int k=s[j][i-1];k<=s[j+1][i];k++)
            if(dp[j][i]>dp[k][i-1]+w[k+1][j]){
              dp[j][i]=dp[k][i-1]+w[k+1][j];
              s[j][i]=k;
    //5        printf("%d %d %d %d
    ",i,j,k,dp[j][i]);
            }
          }
      /*for(int l=1;l<=n;l++)
        for(int i=1;i+l<=n;++)
          printf("w[%d][%d]=%d
    ",i,i+l,w[i][i+l]);*/
      printf("%lld
    ",dp[n][p]);
      return 0;
    }
  • 相关阅读:
    自定义view代码
    省份封装代码
    监听锁屏广播,开启1个像素的Activity
    双进程守护
    新增,查询,删除,修改下方即可
    #Android笔记#解决textview使用SpannableString实现图文混排并设置了行高时,图片与文字显示混乱
    显示地图
    局部页面传值Model
    JS的跳转
    helper实现隐藏前台特效
  • 原文地址:https://www.cnblogs.com/dreagonm/p/9587971.html
Copyright © 2011-2022 走看看