zoukankan      html  css  js  c++  java
  • [CF293B] Distinct Paths

    问题描述

    给定一个 n*m 的矩形色板,有 k 种不同的颜料,有些格子已经填上了某种颜色,现在 需要将其他格子也填上颜色,使得从左上角到右下角的任意路径经过的格子都不会出现两种 及以上相同的颜色。路径只能沿着相邻的格子,且只能向下或者向右。 计算所有可能的方案,结果对 1000000007 (10^9 + 7)求模。

    输入格式

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

    输出格式

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

    样例输入

    2 2 4
    0 0
    0 0

    样例输出

    48

    解析

    首先,从(1,1)到(n,m)的路径长度为n+m-1,那么如果颜色种类数小于n+m-1,无论如何都不存在解。所以,我们把n和m的范围缩小到了10。

    观察条件:从左上角到右下角的任意路径经过的格子都不会出现两种及以上相同的颜色。既然是任意路径,那么不难得到推论,一个格子的左上方不能出现和自己相同的颜色。而颜色种类只有10,不妨用状压的方法储存一个点左上角出现过的颜色集合。具体的,设(f[i][j])表示(i , j)左上角出现过的颜色集合,则

    [f[i][j]=f[i-1][j] | f[i][j-1] ]

    还有一个剪枝。如果在某个格子上,某种颜色是第一次出现,那么这个格子上其他第一次出现的颜色得到的方案数和这个颜色是相同的,不必重复计算。

    代码

    #include <iostream>
    #include <cstdio>
    #define N 1002
    using namespace std;
    const int mod=1000000007;
    int n,m,k,i,j,a[N][N],vis[12],col[N][N];
    int read()
    {
    	char c=getchar();
    	int w=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c<='9'&&c>='0'){
    		w=w*10+c-'0';
    		c=getchar();
    	}
    	return w;
    }
    int count(int x)
    {
    	int ans=0;
    	for(int i=0;(1<<i)<=x;i++){
    		if(x&(1<<i)) ans++;
    	}
    	return ans;
    }
    int dfs(int x,int y)
    {
    	if(y==m+1) x++,y=1;
    	if(x==n+1) return 1;
    	int s=(col[x-1][y]|col[x][y-1])^((1<<k)-1),ans=0,tmp=-1;
    	if(n-x+m-y+1>count(s)) return 0;
    	for(int i=0;(1<<i)<=s;i++){
    		if(s&(1<<i)&&(a[x][y]==0||a[x][y]==i+1)){
    			col[x][y]=(col[x][y-1]|col[x-1][y]|(1<<i));
    			vis[i+1]++;
    			if(vis[i+1]==1){
    				if(tmp==-1) tmp=dfs(x,y+1);
    				ans=(ans+tmp)%mod;
    			}
    			else ans=(ans+dfs(x,y+1))%mod;
    			vis[i+1]--;
    		}
    	}
    	return ans;
    }
    int main()
    {
    	n=read();m=read();k=read();
    	for(i=1;i<=n;i++){
    		for(j=1;j<=m;j++){
    			a[i][j]=read();
    			vis[a[i][j]]++;
    		}
    	}
    	if(n+m-1>k) puts("0");
    	else printf("%d
    ",dfs(1,1));
    	return 0;
    }
    
  • 相关阅读:
    springboot项目在IDEA根据不同的开发人员读取不同的配置文件
    Idea中一个服务按多个端口同时启动
    修改feign解析器替换json
    Intellij IDEA中启动多个微服务--开启Run Dashboard管理
    解决springboot乱码和window cmd乱码
    调用远程linux服务器shell脚本
    cp复制命令详解
    ftp列出具体目录的所有目录,和目录按照文件类型列出
    Linux下Redis开机自启(Centos)
    vsftpd 配置上传失败553
  • 原文地址:https://www.cnblogs.com/LSlzf/p/11789897.html
Copyright © 2011-2022 走看看