回来看看,顺手抢个最优解
ps:这份代码在洛谷也是最优解

#include<bits/stdc++.h>
using namespace std;
const int N=17,INF=0x3f3f3f3f;
int n,m,r,c,a[N][N],sum[N][N],d[N],dp[N][N],ans=INF,sel[N];
int zz[N][N][N],ymq[N][N][N];  //小彩蛋,ymq是zz男朋友的名字缩写哦~
//快读和快写都省略了判断正负的部分,凹点时间
inline int rd()//inline微微提速
{
    int x=0;char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();//使用位运算代替乘法,加加速
    return x;
}
void wr(int x)
{
    if(x>9) wr(x/10);
    putchar(x%10+'0');
}
void dfs(int dep)
{
    if(dep>r)
    {
        for(int i=1;i<=m;++i)
            for(int j=1;j<=c;++j)
                dp[i][j]=INF;
        for(int i=1;i<=m;++i)dp[i][1]=d[i]; //防止dp[i][1]在循环里多跑,直接预处理
        for(int j=2;j<=c;++j)
            for(int i=j;i<=m;++i)
            {
                int mn=INF;
                for(int k=j-1;k<i;++k)
                    if(dp[k][j-1]<INF)
                        mn=min(mn,dp[k][j-1]+sum[k][i]);
                dp[i][j]=mn+d[i];
            }
        for(int i=c;i<=m;++i)
            if(dp[i][c]<ans)//这里理论上可以并到上面的循环里,但zz很懒捏~
                ans=dp[i][c];
        return;
    }
    for(int i=(dep==1?1:sel[dep-1]+1);i<=n-(r-dep);++i)//简单剪枝
    {
        sel[dep]=i;
        if(dep>1)//对sum和d数组的处理原本应该放在dfs终止判断里,但zz选择边dfs边预处理,节省时间
        {
            int p=sel[dep-1];
            for(int j=1;j<=m;++j)d[j]+=zz[p][i][j];
        }
        for(int x=1;x<m;++x)
            for(int y=x+1;y<=m;++y)
                sum[x][y]+=ymq[x][y][i];
        dfs(dep+1);
        if(dep>1)//回溯,边dfs边预处理的瓶颈,只要能删掉这个回溯,速度直接翻倍
        {
            int p=sel[dep-1];
            for(int j=1;j<=m;++j)d[j]-=zz[p][i][j];
        }
        for(int x=1;x<m;++x)
            for(int y=x+1;y<=m;++y)
                sum[x][y]-=ymq[x][y][i];
    }
}
int main()
{
    n=rd();m=rd();r=rd();c=rd();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            a[i][j]=rd();
    for(int i=1;i<n;++i)//提前处理好abs运算,以空间换时间
        for(int j=i+1;j<=n;++j)//zz和ymq的爱恨情仇qwq
            for(int k=1;k<=m;++k)
                zz[i][j][k]=zz[j][i][k]=abs(a[i][k]-a[j][k]);
    for(int i=1;i<m;++i)
        for(int j=i+1;j<=m;++j)
            for(int k=1;k<=n;++k)
                ymq[i][j][k]=ymq[j][i][k]=abs(a[k][i]-a[k][j]);
    dfs(1);
    wr(ans);
    return 0;
}

2 条评论

  • 写代码要细心呐;
    第四行的分号是中文的,要改成英文的;

    • 仔细看的话可以发现第四行和第五行的分号长得不一样

    • @ 2026-11-02 21:42:55

      打注释的时候不小心删的,没切输入法就顺手补上了

    • @ 2026-11-02 21:45:45

      老子辛辛苦苦抢的最优解他妈是让你来抄的吗?不要脸的东西你知道这份代码老子凹了多长时间吗??你他妈就复制递交一下还来我评论区底下教育我,不来讨论区讨论点有用的东西吗???

  • @ 2026-10-29 22:36:22

    这里是zz的小号,QQ号3569070051,欢迎大家加我awa
    zz是盛泽二中22届的猫咪学长,快来骚扰他吧qwq

  • 1

信息

ID
1520
难度
9
分类
(无)
标签
递交数
32
已通过
2
通过率
6%
被复制
6
上传者