• LOJ3246 Cave Paintings


    Cave Paintings

    Bessie 成为了一名艺术家,正在创作壁画!她现在正在创作的作品是一个高为 (N) 的方阵,方阵的每行都由 (M) 个方格组成。每个方格是空的,画了石头,或者画了水。Bessie 已经画上了包含石头的方格,包括整幅画作的边界。她现在想要将某些空的方格画上水,使得如果这幅画是真实的,其中应当不存在水的净移动。定义从上到下第 (i) 行的方格的高度为 (N+1−i)。Bessie 想要她的画作满足以下限制:

    假设方格 (a) 画的是水。那么如果存在一条从 (a) 到方格 (b) 的路径,由高度不超过 (a) 的空的方格或是有水的方格组成,路径中每相邻两个方格都有一条公共边,那么 (b) 画的也是水。

    求 Bessie 可以创作的不同作品的数量模 (10^9+7) 的余数。Bessie 可以将任意数量的空格画上水,包括不画以及全画。

    对于 (100\%) 的数据,保证 (1le N, Mle 10^3)

    题解

    https://jklover.hs-blog.cf/2020/06/10/Loj-3246-Cave-Paintings/#more

    树形 dp.

    重要性质:如果两个点能通过本行及下方的点四连通的点缩在一起,它们的方案一定是一样的.

    把这种点缩在一起,然后限制一定是森林。

    简单的树形 dp 即可统计方案数,可以不显式建树,用并查集维护即可.

    CO int N=1e3+10;
    char str[N][N];
    int idx[N][N];
    int dp[N*N],fa[N*N];
    
    int find(int x){
    	return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    int main(){
    	int n=read<int>(),m=read<int>();
    	for(int i=1;i<=n;++i) scanf("%s",str[i]+1);
    	int num=0;
    	for(int i=n-1;i>=2;--i){
    		int old=num;
    		for(int j=2;j<=m-1;++j)if(str[i][j]=='.'){
    			if(str[i][j-1]=='#') dp[++num]=1,fa[num]=num;
    			idx[i][j]=num;
    			if(str[i+1][j]=='.'){
    				int tmp=find(idx[i+1][j]);
    				if(tmp!=num) dp[num]=mul(dp[num],dp[tmp]),fa[tmp]=num;
    			}
    		}
    		for(int j=old+1;j<=num;++j)if(find(j)==j) dp[j]=add(dp[j],1);
    	}
    	int ans=1;
    	for(int i=1;i<=num;++i)if(find(i)==i) ans=mul(ans,dp[i]);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Mysql必知必会
    KafKa简介和利用docker配置kafka集群及开发环境
    深入理解python
    性能测试报告模板
    Zookeeper的基本原理(zk架构、zk存储结构、watch机制、独立安装zk、集群间同步复制)
    Shell命令和流程控制[linux常用命令的使用]
    Javascrip之BOM
    分布式文件系统HDFS-部署和配置
    分布式计算框架-Spark(spark环境搭建、生态环境、运行架构)
    框架—Mybatis搭建
  • 原文地址:https://www.cnblogs.com/autoint/p/13195473.html
Copyright © 2020-2023  润新知