1 条题解

  • 0
    @ 2022-10-19 20:40:42

    这道题就是一个二维前缀和再加一个dfs遍历全部横切的情况然后找到最小切数的题,看了发的题解才明白,太菜了太菜了👀️

    #include
    using namespace std;
    const int N=1010;
    const int M=12;
    char g[M][N]; 读入的数组
    int sum[M][N];求二维前缀和的数组
    int a[M];记录的横切面第几刀切到第几行
    int n,m,k; 行列条件
    int ans=M*N;初始化答案,最多全部行全部列
    
    bool check(int cnt,int l,int r)
    {
    a[cnt+1]=n;把最后一行加上去判断
    for(int i=1;i<=cnt+1;i++)
    {
    int x1=a[i];
    int x2=a[i-1];用当前这刀和上一刀当做两个横切面
    int t=sum[x1][r]-sum[x1][l]-sum[x2][r]+sum[x2][l];这里和学的二维前缀和有一点出入,这是因为我们不要分割线上的奶所以都没加减一;
    if(t>k) return false;如果不满足条件return false
    }
    return true;这是所有的分割块都满足
    }
    void solve(int cnt)
    {
    int tot=cnt;切的刀数首先加上横着切的刀数
    
    int l=0;记录上一个纵向分割线
    for(int r=1;r<=m;r++)遍历所有的列寻找最小刀数
    {
    if(!check(cnt,l,r))
    {	
    l=r-1;把r的前一列当作分割线,也就是这一块不要第r-1列的奶了
    tot++;刀数++
    if(!check(cnt,l,r))再检查一遍,不要了后是否满足,还不满足则直接pass掉这一种横切刀数的情况
    {
    return ;
    }
    
    }
    }
    ans=min(ans,tot);
    return ;
    
    
    }
    void dfs(int u,int cnt)寻找所有的横切刀数的情况
    {
    if(u==n)找到头了,开始解决问题
    {
    solve(cnt);这里的a[]就已经存好cnt刀了
    return ;
    }
    dfs(u+1,cnt);到下一个行数
    a[cnt+1]=u;第cnt+1刀切的第u行
    dfs(u+1,cnt+1);到下一行,并且存了一刀
    return ;
    }
    int main()
    {
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
    {
    cin>>g[i]+1;
    }
    for(int i=1;i<=n;i++)
    {
    for(int j=1;j<=m;j++)
    {
    sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+g[i][j]-'0';
    
    }
    }
    dfs(1,0);
    cout<ans<<endl
    return 0;
    }
    

    信息

    ID
    20941
    时间
    2000ms
    内存
    1024MiB
    难度
    6
    标签
    (无)
    递交数
    85
    已通过
    25
    上传者