zoukankan      html  css  js  c++  java
  • ZOJ-1234 UVA-10271 DP

      最近觉得动态规划真的很练脑子,对建模以及思维方法有很大帮助,线段树被卡到有点起不来的感觉

    最近仔细思考了一下动态规划的思想,无非是由局部最优解得到全局最优解,由此类推,发现,像最短路和最小生成树其实都是动态规划的思想在里面。

    这题Chopstick,在建立状态 和 怎样递推 是两个难点。

    在建立状态方面,通过dp[i][j],n-i+1为可选的筷子数,j为已选筷子组数,所以最终要求的结果自然是 dp[1][k].

    递推方面,要注意两个细节,第一,每一组的那两根短筷子,必定是相邻的,可以反证法证明。第二,那根长筷子,如果采取逆推方式,就可以不用管了,因为逆推只要保证前面有长筷子即可。。。

    for(i=n-2;i>=1;i--)

     for (j=1;j<=k;j++)

      dp[i][j]=min(dp[i+1][j],dp[i+2][j-1]+badness) (n-i+1>3*j)(即有筷子可选。)(关于为什么是i+2,我想了有一会儿,后来想通了,因为最长的那根筷子不一定要是跟这两根短的是连续的,只要序列前有长筷子即可,故只要往前找两根前的状态即可)。

     dp[i][j]=dp[i+2][j-1]+badness(n-j+1==3*j) 这个时候筷子数刚好满足要挑选的筷子组数,因此无其他筷子可选,只有就近两支可以、。。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int min(int a,int b)
    {
        if (a<b) return a;
        return b;
    }
    int dp[5005][1050];
    int a[5005];
    int main()
    {
        int i,j;
        int t,n,k;
        scanf("%d",&t);
        while (t--)
        {
         scanf("%d%d",&k,&n);
         k+=8;
         for (i=1;i<=n;i++)
            scanf("%d",&a[i]);
         for (i=1;i<=n;i++)
         {
            dp[i][0]=0;
         }
         for (i=n;i>=n-1;i--)
         {
            for (j=1;j<=k;j++)
                dp[i][j]=200000000;
         }
         for (i=n-2;i>=1;i--)
         {
            for (j=1;j<=k&&n-i+1>=3*j;j++)
            {
                if (n-i+1>3*j)
                {
                    dp[i][j]=min(dp[i+1][j],dp[i+2][j-1]+(a[i+1]-a[i])*(a[i+1]-a[i]));
                }
                else
                    dp[i][j]=dp[i+2][j-1]+(a[i+1]-a[i])*(a[i+1]-a[i]);
            }
         }
         printf("%d
    ",dp[1][k]);
        }
        return 0;
    }
  • 相关阅读:
    159
    158
    157
    156
    155
    高中生都能看懂的莫比乌斯反演
    洛谷 P4449 于神之怒加强版
    洛谷 P3455 [POI2007]ZAP-Queries
    洛谷 P1829 [国家集训队]Crash的数字表格 / JZPTAB
    Dirichlet卷积
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3309559.html
Copyright © 2011-2022 走看看