zoukankan      html  css  js  c++  java
  • CF293B Distinct Paths题解

    CF293B Distinct Paths

    题意

    给定一个(n imes m)的矩形色板,有kk种不同的颜料,有些格子已经填上了某种颜色,现在需要将其他格子也填上颜色,使得从左上角到右下角的任意路径经过的格子都不会出现两种及以上相同的颜色。路径只能沿着相邻的格子,且只能向下或者向右。

    计算所有可能的方案,结果对 (1000000007 (10^9 + 7))

    输入及输出格式

    输入格式

    第一行,三个整数$ n, m, k (1 le n, m le 1000, 1 le k le 10)$;

    接下来(n)行,每行包含(m)个整数,表示颜色。其中(0)表示未涂色,非(0)表示颜色的编号, 颜色编号为(1)(k)

    输出格式

    一行,一个整数,表示涂色方案对$ 1000000007 (10^9 + 7)$求模的结果。

    样例

    此处就不挂了:传送门

    思路

    看似数据很大:(n, m, k (1 le n, m le 1000, 1 le k le 10)),但是,(k<n+m-1) 时,可以直接输出(0)。因为无法走完一条路径(一条路径长度为(n+m-1),因为是只能向下、向右走)。

    那么实际数据范围很小,大概是$n+m-1 le 10 $左右吧。

    这么小的范围很容易就可想到(dfs)。这里有两个优化,一个是如果搜到一半,发现剩下的颜色不够用了就直接(return)。还有一个就是利用颜色(A)与颜色(B)的先后次序问题,路径(AB)与路径(BA)并不是同一种方案,所以搜索时如果搜到是第一次时,就可以直接乘(now)就可以省去很多(dfs)

    代码很丑,勿喷。

    #include<algorithm>
    #include<bitset>
    #include<complex>
    #include<deque>
    #include<exception>
    #include<fstream>
    #include<functional>
    #include<iomanip>
    #include<ios>
    #include<iosfwd>
    #include<iostream>
    #include<istream>
    #include<iterator>
    #include<limits>
    #include<list>
    #include<locale>
    #include<map>
    #include<memory>
    #include<new>
    #include<numeric>
    #include<ostream>
    #include<queue>
    #include<set>
    #include<sstream>
    #include<stack>
    #include<stdexcept>
    #include<streambuf>
    #include<string>
    #include<typeinfo>
    #include<utility>
    #include<valarray>
    #include<vector>
    #include<cstring>
    #include<cmath>
    #define MOD 1000000007
    using namespace std;//恶心的头文件
    inline int read(){
    	char ch=getchar();int res=0,f=1;
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar();
    	return res*f;
    }//读入优化
    inline void write(int zx){
    	if(zx<0) zx=-zx,putchar('-');
    	if(zx<10) putchar(zx+'0');
    	else{
    		write(zx/10);
    		putchar(zx%10+'0');
    	}
    }//输出优化
    int n,m,k,cnt[50],a[50][50],sum,f[30][30],ps,ans,vv;
    int dfs(int x,int y){
    	if(y==m+1){return dfs(x+1,1);}
    	if(x==n+1) return 1;
    	int S=0,num=0,mar=0,res=0,las=0;
    	f[x][y]=f[x-1][y]|f[x][y-1];
    	for(int i=1;i<=k;i++){
    		if(!(f[x][y]&(1<<i-1))) ++num;
    	}
    	if(num<n+m-x-y+1) return 0;//第一个优化
    	if(a[x][y]==0){
    		for(int i=1;i<=k;i++){
    			if(!(f[x][y]&(1<<i-1))){
    				if(cnt[i]==0){
    					if(mar) res+=las,res%=MOD;//第二个优化
    					else{
    						mar=1;
    						cnt[i]++;
    						f[x][y]|=1<<i-1;
    						las=dfs(x,y+1);
    						f[x][y]^=1<<i-1;
    						cnt[i]--;
    						res+=las;
    						res%=MOD;
    					}
    					continue ;
    				}
    				cnt[i]++;
    				f[x][y]|=1<<i-1;
    				res+=dfs(x,y+1);
    				f[x][y]^=1<<i-1;
    				cnt[i]--;
    				res%=MOD;
    			}
    		}
    	}else{
    		if(!(f[x][y]&(1<<a[x][y]-1))){
    			f[x][y]|=1<<a[x][y]-1;
    			res+=dfs(x,y+1);
    			f[x][y]^=1<<a[x][y]-1;
    			res%=MOD;
    		}
    	}
    	return res;
    }
    int main(){
    	n=read();m=read();k=read();
    	vv=n+m-1;
    	if(k<vv){//开始先特判
    		puts("0");
    		return 0;
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			a[i][j]=read();
    			cnt[a[i][j]]++;
    		}
    	}
    	ans=dfs(1,1);
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    致初学者:PHP比ASP优秀的七个理由
    有情人终成眷属为好友hualex2006.12.9结婚祝福
    有情人终成眷属为好友hualex2006.12.9结婚祝福
    各种查找算法效率比较
    实习三 树、二叉树及其应用 (题目:唯一地确定一棵二叉树 )
    hdu 2188 选拔志愿者(博弈)
    hdu 1050Moving Tables(贪心)
    实习一 线性表及其应用 (题目:一元稀疏多项式的加法运算 )
    实习六 农夫过河问题
    实习二 栈、队列和递归算法设计 (题目:停车场管理 )
  • 原文地址:https://www.cnblogs.com/yzx1798106406/p/9871478.html
Copyright © 2011-2022 走看看