zoukankan      html  css  js  c++  java
  • [USACO20DEC] Spaceship P 题解

    solution:

    (dp_{a,f_1,b,f_2,c})表示从a到b,使用最大的按钮编号$leq $c。

    • (f_1)表示是否对第一个按的有要求,如果有,则(a=s)需要先按下(b_s)
    • (f_2)表示是否对最后一个有要求,如果有,则(b=t),最后要按下(b_t)

    先考虑简单的情况:(f_{1}=f_{2}=0),以下用(dp_{a,b,c})代替(dp_{a,0,b,0,c,0})

    有两种转移:

    • 按的最大的<c,则(dp_{a,b,c}+=dp_{a,b,c-1})

    • 按的最大的=c, 则(dp_{a,b,c}+=sum _{r}(sum _{i,e[i,r]=1} dp_{a,i,c-1})*(sum _{j,e[r,j]=1}dp_{j,b,c-1})),显然这两个部分都是可以(O(N^4))预处理的。设(g_{a,r,c}=sum_{e[b,r]=1} dp_{a,b,c},f_{r,a,c}=sum _{e[r,b]=1} dp_{b,a,c})。则(dp_{a,b,c}+=sum _{r} g_{a,r,c-1} imes f_{r,b,c-1})

    这部分的转移是(O(N^4))的。

    可以发现(f_1=f_2=0)的部分对于所有的询问都是互不影响的。所以我们可以先(O(N^4))的算出这些答案。

    然后我们再考虑(f_1=1)的情况,可以发现有用的状态的a一定等于s。同理(f_2=1)的时候,有用状态的b等于t。

    所以对于每一个询问,有用状态是(O(N^2K))级别的。

    总时间复杂度为(O(N^3*K+N^2*Q*K))

    /*
    {
    ######################
    #       Author       #
    #        Gary        #
    #        2020        #
    ######################
    */
    #include<bits/stdc++.h>
    #define rb(a,b,c) for(int a=b;a<=c;++a)
    #define rl(a,b,c) for(int a=b;a>=c;--a)
    #define LL long long
    #define IT iterator
    #define PB push_back
    #define II(a,b) make_pair(a,b)
    #define FIR first
    #define SEC second
    #define FREO freopen("check.out","w",stdout)
    #define rep(a,b) for(int a=0;a<b;++a)
    #define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
    #define random(a) rng()%a
    #define ALL(a) a.begin(),a.end()
    #define POB pop_back
    #define ff fflush(stdout)
    #define fastio ios::sync_with_stdio(false)
    #define check_min(a,b) a=min(a,b)
    #define check_max(a,b) a=max(a,b)
    using namespace std;
    //inline int read(){
    //    int x=0;
    //    char ch=getchar();
    //    while(ch<'0'||ch>'9'){
    //        ch=getchar();
    //    }
    //    while(ch>='0'&&ch<='9'){
    //        x=(x<<1)+(x<<3)+(ch^48);
    //        ch=getchar();
    //    }
    //    return x;
    //}
    const int INF=0x3f3f3f3f;
    typedef pair<int,int> mp;
    /*}
    */
    int n,k,q;
    const int MAXN=60+1; 
    int dp[2][2][MAXN][MAXN][MAXN],g[2][MAXN][MAXN][MAXN],f[2][MAXN][MAXN][MAXN];
    bool e[MAXN][MAXN];
    const int MOD=1e9+7;
    void add(int& x,int y){
    	x+=y;
    	if(x>=MOD) x-=MOD;
    }
    void normal(){
    	rb(c,1,k){
    		rb(r,1,n){
    			rb(a,1,n)rb(b,1,n){
    				if(e[b][r]){
    					add(g[0][r][a][c],dp[0][0][a][b][c-1]);
    				}		
    				if(e[r][a]){
    					add(f[0][r][b][c],dp[0][0][a][b][c-1]);
    				}
    			}
    			add(f[0][r][r][c],1);
    			add(g[0][r][r][c],1);
    		}
    		rb(i,1,n) rb(j,1,n){
    			dp[0][0][i][j][c]=dp[0][0][i][j][c-1];
    			rb(r,1,n) add(dp[0][0][i][j][c],1ll*g[0][r][i][c]*f[0][r][j][c]%MOD);
    		}
    	}
    }
    int bs,s,bt,t;
    int calc(){
    	rep(i,2) rep(j,2) if(i+j) memset(dp[i][j],0,sizeof(dp[i][j]));
    	memset(g[1],0,sizeof(g[1]));
    	memset(f[1],0,sizeof(f[1]));
    	rb(c,1,k){
    		rb(r,1,n){
    			rb(i,1,n){
    				if(e[i][r]){
    					add(g[1][r][s][c],dp[1][0][s][i][c-1]);
    				}
    				if(e[r][i]){
    					add(f[1][r][t][c],dp[0][1][i][t][c-1]);
    				}
    			}
    		}
    		if(c==bs){
    			add(g[1][s][s][c],1);
    		}
    		if(c==bt){
    			add(f[1][t][t][c],1);	
    		}
    		add(dp[1][1][s][t][c],dp[1][1][s][t][c-1]);
    		rb(i,1,n){
    			add(dp[1][0][s][i][c],dp[1][0][s][i][c-1]);
    			add(dp[0][1][i][t][c],dp[0][1][i][t][c-1]);
    			rb(r,1,n){
    				add(dp[1][0][s][i][c],1ll*g[1][r][s][c]*f[0][r][i][c]%MOD);
    				add(dp[0][1][i][t][c],1ll*g[0][r][i][c]*f[1][r][t][c]%MOD);
    			}
    		}
    		rb(r,1,n)
    			add(dp[1][1][s][t][c],1ll*g[1][r][s][c]*f[1][r][t][c]%MOD);
    	}
    	return dp[1][1][s][t][k];
    }
    int main(){
    	scanf("%d%d%d",&n,&k,&q);
    	rb(i,1,n) rb(j,1,n){
    		char c;
    		cin>>c;
    		e[i][j]=c-'0';
    	}
    	normal(); 
    	rb(T,1,q){
    		scanf("%d%d%d%d",&bs,&s,&bt,&t);
    		printf("%d
    ",calc());
    	}		
    	return 0;
    }
    /*
    6 20 5
    110101
    011001
    001111
    101111
    111010
    000001
    2 5 2 5
    6 1 5 2
    3 4 8 3
    9 3 3 5
    5 1 3 4
    */
    
  • 相关阅读:
    python入门1
    查找字段 和查找组件
    DBGRID 拖动滚动条 和 鼠标滚轮的问题
    数据集 过滤时 RecordCount 属性
    查找字段 如何 过滤
    数据集控件 放在 数据模块 上后,如何写事件代码
    取TTable 过滤后的记录数
    判断 Windows操作系统是32位还是64位
    MatchText MatchStr 区别
    EClassNotFound
  • 原文地址:https://www.cnblogs.com/gary-2005/p/14189632.html
Copyright © 2011-2022 走看看