1 条题解

  • 0
    @ 2025-8-24 22:02:52

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Treeloveswater
    **

    搬运于2025-08-24 22:02:52,当前版本为作者最后更新于2018-06-22 09:58:42,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    Emmmm和出题人交流了一下,发现自己的算法没问题

    也成功拿到最快的44ms

    我来说一下我的做法吧,这个做法的复杂度非常的优越

    首先我们肯定是要 2^k去枚举每个部分的状态的

    复杂度优化的关键在于Dp

    我们发现如果固定扣的分数,那么行数自然是尽量大。在行数一样大的情况下自然是最后一行字越多越好。

    我们发现可以在dp的基础上贪心。

    我们设f[i][j]为 dp到第i个句子,现在扣了j分

    f[i][j]是一个pair,保存着两个值 行数 最后一行的字数

    这样Dp的复杂度是 n·cnt·S cnt是不会扣到0的部分的数量

    2^k种状态的cnt加和是 k*2^(k-1)

    所以最后的复杂度是 2^(k-1)kSn == 80 · 200 · 200

    非常优越的复杂度,甚至可以把S,n提高到300都可以做

    附上代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    pair<int,int> f[201][1005];
    int n,m,L,K,S,C;
    int A[205];
    int s[205][11];
    bool vis[201][1005],ok[11];
    void up(int i,int j,int a,int b){
        if(!vis[i][j]){
            vis[i][j]=1;
            f[i][j]=make_pair(a,b);
        }
        else{
            if(f[i][j].first>a)return;
            if(f[i][j].first<a)
                f[i][j]=make_pair(a,b);
            else
                f[i][j].second=max(f[i][j].second,b);
        }
    }
    int main(){
        scanf("%d%d%d%d%d%d",&n,&m,&L,&K,&S,&C);
        for(int i=1;i<=n;i++) scanf("%d",&A[i]);
        for(int i=1;i<n;i++)
            for(int j=0;j<K;j++) 
                scanf("%d",&s[i][j]);
        int ans=0;
        for(int t=1;t<(1<<K);t++){
            memset(vis,0,sizeof(vis));
            for(int i=0;i<K;i++) ok[i]=(t>>i)&1;
            int cnt=0,a,b,c,d,e;
            for(int i=0;i<K;i++) cnt+=ok[i];
            a=(A[1]+2)/L;b=(A[1]+2)%L;
            if(!b) b=L;
            else a++;
            f[1][0]=make_pair(a,b);vis[1][0]=1;
            for(int i=1;i<n;i++)
                for(int j=0;j<=cnt*S;j++)
                    if(vis[i][j]){
                        a=f[i][j].first,b=f[i][j].second;
                        e=0;
                        c=a-1+(b+A[i+1])/L,d=(b+A[i+1])%L;
                        if(!d) d=L; else c++;
                        for(int k=0;k<K;k++) if(ok[k]&&s[i][k]<0) e-=s[i][k];
                        if(j+e<=cnt*S) up(i+1,j+e,c,d);
                        e=0;
                        c=a+(A[i+1]+2)/L,d=(A[i+1]+2)%L;
                        if(!d) d=L; else c++;
                        for(int k=0;k<K;k++) if(ok[k]&&s[i][k]>0) e+=s[i][k];
                        if(j+e<=cnt*S) up(i+1,j+e,c,d);
                    }
            int total=cnt*S,zm;
            for(int j=0;j<=cnt*S;j++) if(vis[n][j]){
                zm=total-j;
                if(f[n][j].first<m) zm-=(m-f[n][j].first)*C;
                ans=max(ans,zm);
            } 
        }
        cout<<ans<<endl;
    }
    
    • 1

    信息

    ID
    3447
    时间
    2000ms
    内存
    512MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者