zoukankan      html  css  js  c++  java
  • [20200720NOIP提高组模拟T1]矩阵的个数

    题目通道:

       https://www.luogu.com.cn/problem/P5784

    题目大意:

     给你一个数n,表示全为非负数的矩阵大小为3*n,给你3个数$c_{1}$、$c_{2}$、$c_{3}$,分别表示矩阵第一、二、三列的数值之和,再给你n个数,表示第$a_{i}$行的数值之和,请你求出满足条件的矩阵的个数.

    solution:

     一开始没什么思路,写了手dfs,直觉特判压缩第三列,复杂度O($n^{2}n!$),显然过不去.接着在dfs基础上考虑记忆搜,数组需开到250*150*150,空间较为吃力,时间也有些紧张,代码也不太好写.所以考虑直接递推dp,滚动数组滚掉一个维度,在$1--n$上考虑状态转移,特判维护第三列数值的合法.

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define R register
    #define next exnttttnext
    #define debug puts("MLG")
    #define mod 100000000000000000
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    inline ll read();
    inline void write(ll x);
    inline void writesp(ll x);
    inline void writeln(ll x);
    ll n,c1,c2,c3;
    ll num[1000],sum[1000];
    ll f[250][250][2];
    int main(){
        n=read();c1=read();c2=read();c3=read();
        for(R ll i=1;i<=n;i++) num[i]=read(),sum[i]=sum[i-1]+num[i];
        if(sum[n]!=c1+c2+c3){
            writeln(0);
            return 0;
        }
        f[0][0][0]=1;
        for(R ll i=1;i<=n;i++){
            for(R ll j=0;j<=sum[i]&&j<=c1;j++){
                for(R ll k=0;k+j<=sum[i]&&k<=c2;k++){
                    f[j][k][i&1]=0;
                    if(sum[i]-j-k>c3) continue;
                    for(R ll u=0;u<=num[i];u++){
                        for(R ll v=0;u+v<=num[i];v++){
                            if(j-u<0||k-v<0||(sum[i]-j-k)-(num[i]-u-v)<0) continue;
                            f[j][k][i&1]+=f[j-u][k-v][(i&1)^1];
                            f[j][k][i&1]%=mod;
                        }
                    }
                }
            }
        }
        writeln(f[c1][c2][n&1]);
    }
    inline ll read(){
        ll x=0,t=1;char ch=getchar();
        while(ch<'0'||ch>'9'){
            if(ch=='-') t=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x*t;
    }
    inline void write(ll x){
        if(x<0){putchar('-');x=-x;}
        if(x<=9){putchar(x+'0');return;}
        write(x/10);putchar(x%10+'0');
    }
    inline void writesp(ll x){
        write(x);putchar(' ');
    }
    inline void writeln(ll x){
        write(x);putchar('
    ');
    }
  • 相关阅读:
    贪心算法1000
    贪心算法1006
    1012
    贪心算法1016
    贪心算法1001
    贪心算法1004
    Java作业1
    指针数组与数组指针的区别
    Java 中对类进行排序的方法(转)
    java习题1
  • 原文地址:https://www.cnblogs.com/ylwtsq/p/13344821.html
Copyright © 2011-2022 走看看