lemon

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
const int INF=1e9+5;
int n,m,k,w,tot,minn=INF,mark;
int f[1005][1005],a[1005],b[101],d[101];
template <class t>void red(t &x)
{
    x=0;
    int w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
    x*=w;
}
void input()
{
    freopen("luogu.txt","r",stdin);
    freopen("lemon.out","w",stdout);
}
int main()
{
    input();
    red(n);
    red(m);
    red(k);
    red(w);
    while(n--)
    {
        memset(f,0x3f,sizeof(f));
        for(int i=0;i<=m;++i)
        {
            f[i][i]=0;
            if(!i)
                continue;
            red(a[i]);
        }
        a[m+1]=w;
        for(int i=2;i<=m+1;++i)
            for(int j=0;j+i<=m+1;++j)
            {
                int e=j+i-1;
                for(int k=j;k<e;++k)
                    if(f[j][k]+f[k+1][e]+a[e+1]-a[j]<f[j][e])
                        f[j][e]=f[j][k]+f[k+1][e]+a[e+1]-a[j];
            }
        printf("%d
",b[++tot]=f[0][m]);
    }
    for(int i=1;i<=tot;++i)
        if(b[i]<minn)
        {
            minn=b[i];
            mark=i;
        }    
    d[1]=0;
    for(int i=2;i<=tot;++i)
        d[i]=(d[i-1]+k)%i;
    printf("
%d",1+abs(d[tot]+1-mark));
    return 0
#include<bits/stdc++.h>using namespace std;const int maxn=1e6+5;const int INF=1e9+5;int n,m,k,w,tot,minn=INF,mark;int f[1005][1005],s[1005][1005],a[1005],b[101],d[101];template <class t>void red(t &x){    x=0;    int w=1;    char ch=getchar();    while(ch<'0'||ch>'9')    {        if(ch=='-')            w=-1;        ch=getchar();    }    while(ch>='0'&&ch<='9')    {        x=(x<<3)+(x<<1)+ch-'0';        ch=getchar();    }    x*=w;}void input(){    freopen("input.txt","r",stdin);    //freopen("lemon9.out","w",stdout);}int main(){    //input();    red(n);    red(m);    red(k);    red(w);    while(n--)    {        memset(f,0x3f,sizeof(f));        for(int i=0;i<=m;++i)        {            f[i][i]=0;            s[i][i]=i;            if(!i)                continue;            red(a[i]);        }        a[m+1]=w;        for(int i=2;i<=m+1;++i)            for(int j=0;j+i<=m+1;++j)            {                int e=j+i-1;                for(int k=s[j][e-1];k<=s[j+1][e];++k)                    if(f[j][k]+f[k+1][e]+a[e+1]-a[j]<f[j][e])                    {                        f[j][e]=f[j][k]+f[k+1][e]+a[e+1]-a[j];                        s[j][e]=k;                    }            }        printf("%d
",b[++tot]=f[0][m]);    }    for(int i=1;i<=tot;++i)        if(b[i]<minn)        {            minn=b[i];            mark=i;        }       d[1]=0;    for(int i=2;i<=tot;++i)        d[i]=(d[i-1]+k)%i;    printf("
%d",1+abs(d[tot]+1-mark));    return 0;}
View Code



首先,它是道区间dp
然后,毒瘤的csy将它卡成了O(n^2)
所以,它是道要用四边形不等式优化的区间dp _(:з」∠)_
csy自己写标程的时候就在这儿卡了一下午
但毒瘤的csy还是不满足
所以,又有了更加丧心病狂的分柠檬,并且想卡成O(n)
然后,失败了QAQ
分柠檬原型是约瑟夫问题
然后,被我魔改了
其一般解法是模拟-》链表-》(特殊情况)公式
还有点良心的csy没有让大家被和她一样被链表折磨,于是本题用公式法(baidu)可解
csy的数据也蛮毒瘤的,在本地跑基本卡着上限过,不知道为什么到了luogu和mzoj上速度蜜汁快了一半,也不知道到底卡没卡住人 _(:з」∠)_


- 20~40 point

  1,2,7,8的m=1,n《=1e3

  O(n^3)可过

- 40~60 point

  1,2,7,8,9,10

  发现O(n^2)的暴力模拟第二问的方法

- 100 point

  四边形不等式优化区间dp

  公式优化约瑟夫问题

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
const int INF=1e9+5;
int n,m,k,w,tot,minn=INF,mark;
int f[1005][1005],s[1005][1005],a[1005],b[101],d[101];
template <class t>void red(t &x)
{
    x=0;
    int w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
    x*=w;
}
void input()
{
    freopen("luogu.txt","r",stdin);
    freopen("lemon.out","w",stdout);
}
int main()
{
    input();
    red(n);
    red(m);
    red(k);
    red(w);
    while(n--)
    {
        memset(f,0x3f,sizeof(f));
        for(int i=0;i<=m;++i)
        {
            f[i][i]=0;
            s[i][i]=i;
            if(!i)
                continue;
            red(a[i]);
        }
        a[m+1]=w;
        for(int i=2;i<=m+1;++i)
            for(int j=0;j+i<=m+1;++j)
            {
                int e=j+i-1;
                for(int k=s[j][e-1];k<=s[j+1][e];++k)
                    if(f[j][k]+f[k+1][e]+a[e+1]-a[j]<f[j][e])
                    {
                        f[j][e]=f[j][k]+f[k+1][e]+a[e+1]-a[j];
                        s[j][e]=k;
                    } 
            }
        printf("%d
",b[++tot]=f[0][m]);
    }
    for(int i=1;i<=tot;++i)
        if(b[i]<minn)
        {
            minn=b[i];
            mark=i;
        }    
    d[1]=0;
    for(int i=2;i<=tot;++i)
        d[i]=(d[i-1]+k)%i;
    printf("
%d",1+abs(d[tot]+1-mark));
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Achensy/p/10886442.html