zoukankan      html  css  js  c++  java
  • HDU 4363

    这题是记忆化搜索很容易想到,但状态却不好设

    dp[i][j][u][d][l][r][k]。对于矩形为i*j,它的四周的颜色分别为u,d,l,r,横竖切的状态为k的种数。

    其中要注意一个问题是,停止不一定是不可进行,而是随时都可以停止,这样就会有一种涂色为对某个矩形而言只涂一种颜色。那么,就必定会有重复的上下矩形只涂两种颜色的重复出现,这样就要减去这些重复的。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL __int64
    using namespace std ;
    const LL MOD=1000000007;
    LL dp[42][42][5][5][5][5][2];
    
    
    void dfs(int i,int j,int u,int d,int l,int r,int w){
    	if(dp[i][j][u][d][l][r][w]!=-1) return ;
    	LL ret=0;
    	for(int c=1;c<=4;c++){
    		if(c!=u&&c!=d&&c!=l&&c!=r) ret++;
    	}
    	if(w==1){
    		for(int h=1;h<i;h++){
    			for(int c=1;c<=4;c++){
    				if(c!=u&&c!=l&&c!=r){
    					dfs(i-h,j,c,d,l,r,0);
    					ret=(ret+dp[i-h][j][c][d][l][r][0])%MOD;
    				}
    			}
    			for(int c=1;c<=4;c++){
    				if(c!=d&&c!=l&&c!=r){
    					dfs(h,j,u,c,l,r,0);
    					ret=(ret+dp[h][j][u][c][l][r][0])%MOD;
    				}
    			}
    		}
    		LL counts=0;
    		for(int c1=1;c1<=4;c1++){
    			if(c1!=u&&c1!=l&&c1!=r){
    				for(int c2=1;c2<=4;c2++){
    					if(c2!=l&&c2!=r&&c2!=c1&&c2!=d)
    					counts++;
    				}
    			}
    		}
    		counts=counts*(i-1);
    		ret=((ret-counts)%MOD+MOD)%MOD;
    	}
    	else{
    		for(int k=1;k<j;k++){
    			for(int c=1;c<=4;c++){
    				if(c!=u&&c!=l&&c!=d){
    					dfs(i,j-k,u,d,c,r,1);
    					ret=(ret+dp[i][j-k][u][d][c][r][1])%MOD;
    				}
    			}
    			for(int c=1;c<=4;c++){
    				if(c!=u&&c!=r&&c!=d){
    					dfs(i,k,u,d,l,c,1);
    					ret=(ret+dp[i][k][u][d][l][c][1])%MOD;
    				}
    			}
    		}
    		LL counts=0;
    		for(int c1=1;c1<=4;c1++){
    			if(c1!=u&&c1!=l&&c1!=d){
    				for(int c2=1;c2<=4;c2++){
    					if(c2!=c1&&c2!=r&&c2!=u&&c2!=d)
    					counts++;
    				}
    			}
    		}
    		counts=counts*(j-1);
    		ret=((ret-counts)%MOD+MOD)%MOD;
    	}
    	dp[i][j][u][d][l][r][w]=ret;
    }
    
    int main(){
    	memset(dp,-1,sizeof(dp));
    	int T,n,m;
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d%d",&n,&m);
    		dfs(n,m,0,0,0,0,1);
    		printf("%I64d
    ",dp[n][m][0][0][0][0][1]);
    	}
    	return 0;
    }
    

      

    写的时候要特别小心,很容易出现BUG。调了我一晚上。

  • 相关阅读:
    4、Work-Queue
    一个简单servlet容器
    一个简单的Web服务器
    jersey实现RESTful接口PUT方法JSON数据传递
    Java数据库连接组件C3P0和DBCP
    C/S架构和B/S架构
    一些同样适用于人生的计算机原理
    网络编程初探--使用UDP协议的简易聊天室
    IO练习--按字节截取字符串
    IO包中的其他类总结
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4426286.html
Copyright © 2011-2022 走看看