zoukankan      html  css  js  c++  java
  • HDU 3480 Division

    HDU_3480

        首先,一个贪心的思路就是如果将元素排个序,选择的一定是连续的区间,因为如果选了两个值,那么这个区间就可以选两个值之间的任何一个值,这样是不会改变这个区间的cost的。

        如果用w[i][j]表示(a[j]-a[i])*(a[j]-a[i]),写出状态转移方程后会得到f[i][j]=min{f[i-1][k-1]+w[k,j]},这个和POJ_1160的状态转移方程是一样的,如果我们能够证明w为凸,那么这个题就可以用四边形不等式优化。

        由于w[i+1][j]-w[i][j]=(a[i]-a[i+1])*(2*a[j]-a[i+1]-a[i]),这个表达式是随着j的增加单调递减的,所以就有w[i+1][j+1]-w[i][j+1]<=w[i+1][j]-w[i][j],也就是w[i][j]+w[i+1][j+1]<=w[i][j+1]+w[i+1][j],所以w是凸的,进而我们就可以放心地使用四边形不等式优化dp了。

        其实,如果我们把状态转移方程写成f[i][j]=min{f[i-1][k-1]+ (a[j]-a[k])*(a[j]-a[k])}的话,不妨假设k的取值x、y满足x<y,且y要比x优,这时就能化简成a[j]>(a[y]*a[y]-a[x]*a[x]+f[i-1][y-1]-f[i-1][x-1])/(2*a[y]-2*a[x]),这样就又变成能够使用斜率优化了,而且用斜率优化比较好用滚动数组实现,能节省不少空间。

    //四边形不等式优化dp
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define MAXD 10010
    #define INF 0x3f3f3f3f
    int N, M, a[MAXD], f[MAXD][MAXD], K[MAXD][MAXD];
    int cmp(const void *_p, const void *_q)
    {
    int *p = (int *)_p, *q = (int *)_q;
    return *p - *q;
    }
    int getw(int x, int y)
    {
    return (a[y] - a[x]) * (a[y] - a[x]);
    }
    void init()
    {
    int i, j, k;
    scanf("%d%d", &N, &M);
    for(i = 1; i <= N; i ++)
    scanf("%d", &a[i]);
    }
    void solve()
    {
    int i, j, k, p, t;
    qsort(a + 1, N, sizeof(a[0]), cmp);
    for(i = 0; i <= N; i ++)
    {
    f[i][i] = 0;
    K[i][i] = i;
    }
    for(i = M + 2; i <= N; i ++)
    K[M + 1][i] = i;
    for(p = 1; p <= N - M; p ++)
    {
    f[0][p] = INF;
    for(i = 1; i <= M; i ++)
    {
    j = i + p;
    f[i][j] = INF;
    for(k = K[i][j - 1]; k <= K[i + 1][j]; k ++)
    {
    t = f[i - 1][k - 1] + getw(k, j);
    if(t < f[i][j])
    {
    f[i][j] = t;
    K[i][j] = k;
    }
    }
    }
    }
    printf("%d\n", f[M][N]);
    }
    int main()
    {
    int t, tt;
    scanf("%d", &t);
    for(tt = 0; tt < t; tt ++)
    {
    init();
    printf("Case %d: ", tt + 1);
    if(M >= N)
    printf("0\n");
    else
    solve();
    }
    return 0;
    }
    //斜率优化+单调队列
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define MAXD 10010
    int N, M, a[MAXD], wa[MAXD], wb[MAXD], *f, *g, q[MAXD];
    int cmp(const void *_p, const void *_q)
    {
    int *p = (int *)_p, *q = (int *)_q;
    return *p - *q;
    }
    void init()
    {
    int i, j, k;
    scanf("%d%d", &N, &M);
    for(i = 1; i <= N; i ++)
    scanf("%d", &a[i]);
    }
    int getw(int x, int y)
    {
    return (a[y] - a[x]) * (a[y] - a[x]);
    }
    int getf(int i)
    {
    return a[i] * a[i] + g[i - 1];
    }
    void solve()
    {
    int i, j, k, front, rear, x, y, z, *t;
    qsort(a + 1, N, sizeof(a[0]), cmp);
    f = wa, g = wb;
    for(i = 1; i <= N; i ++)
    g[i] = getw(1, i);
    for(i = 2; i <= M; i ++)
    {
    front = rear = 0;
    q[rear ++] = i;
    for(j = i; j <= N; j ++)
    {
    while(front < rear - 1)
    {
    x = q[front], y = q[front + 1];
    if(a[j] * 2 * (a[y] - a[x]) < getf(y) - getf(x))
    break;
    ++ front;
    }
    x = q[front];
    f[j] = g[x - 1] + getw(x, j);
    if(j < N)
    {
    q[rear] = j + 1;
    for(k = rear - 1; k > front; k --)
    {
    x = q[k - 1], y = q[k], z = q[k + 1];
    if((getf(y) - getf(x)) * (a[z] - a[y]) < (getf(z) - getf(y)) * (a[y] - a[x]))
    break;
    q[rear = k] = q[k + 1];
    }
    ++ rear;
    }
    }
    t = f, f = g, g = t;
    }
    printf("%d\n", g[N]);
    }
    int main()
    {
    int t, tt;
    scanf("%d", &t);
    for(tt = 0; tt < t; tt ++)
    {
    init();
    printf("Case %d: ", tt + 1);
    if(M >= N)
    printf("0\n");
    else
    solve();
    }
    return 0;
    }



  • 相关阅读:
    [转]validation验证控件案例以及正则表达式中几个特殊符号的说明!
    [转]Writing Installs With The Windows Installer Is A Pain!
    [转]配置子报表和钻取报表
    微软的软件授权及保护服务(SLPS)
    VS2005下源代码管理的VSS2005的登录ID设置
    [书目20080428]Google API开发详解:Google Maps与Google Earth双剑合璧
    GridView 的EmptyDataText 及 EmptyDataTemplate
    [转]用C#和SQL获得当前月的第一天和最后一天
    [引]ASP.NET IIS 注册工具 (Aspnet_regiis.exe)
    [转]开发Silverlight 2应用程序的准备工作
  • 原文地址:https://www.cnblogs.com/staginner/p/2394329.html
Copyright © 2011-2022 走看看