zoukankan      html  css  js  c++  java
  • 【题解】多边形染色

    Link

    蒟蒻做的为数不多的环形(dp),技巧不到位,写题解来总结一下。

    ( ext{Solution:})

    (dp)柿子还是很好推出来的:(dp[i][j])表示地(i)个点染色是(j)的方案数。先考虑没有限制的转移:

    [dp[i][j]=sum_{k ot=j} dp[i-1][k] ]

    最后注意一下(1,n)的限制。

    这题多了三个操作,分别是:限制相邻两个颜色一样,限制固定颜色,以及限制不能填的颜色。

    那么我们分类讨论一下,对于有相邻颜色一样的点,就可以从上一步的相同颜色转移而来,同时注意一下是不是有其他两种操作即可。

    对于没有相邻颜色限制的点,考虑其他限制,有固定颜色的枚举上一个所有不同于固定颜色的颜色转移;有不能填的颜色的枚举上一个所有颜色特判一下就行。

    这题的主要难点在于环形后效性的处理。对于我这种没怎么写过环形(dp)的人,还是有点生疏。

    对于这个题,瞪眼法看出最后一个颜色与第一个颜色是有关联的。那么我们可以钦定第一个点的颜色,进行(c)(dp)就可以方便地处理后效性啦。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int mod=987654321;
    int n,m,c,ans;
    int col[50010],dp[50010][11];
    //dp[i]表示i这个点是p颜色,1-i一共的方案数
    int vis[50010],sum[50010];
    int dislike[50010][20];
    signed main() {
    	scanf("%lld%lld%lld",&n,&m,&c);
    	for(int i=1; i<=m; ++i) {
    		int opt,x,y;
    		scanf("%lld%lld%lld",&opt,&x,&y);
    		if(opt==1)for(int i=1;i<=c;++i){if(i!=y)dislike[x][i]=1;}
    		if(opt==2)dislike[x][y]=1;
    		if(opt==3) {
    			if(y>x)swap(x,y);
    			vis[x]=y;
    		}
    	}
    	//vis[big]=small
    	/*if(col[1]==0){
    		for(int i=1;i<=c;++i)dp[1][i]=1;
    	}
    	if(col[1]!=0){
    		if(col[1]>0)dp[1][col[1]]=1;
    		else{
    			for(int i=1;i<=c;++i){
    				if(i==-col[1])continue;
    				dp[1][i]=1;
    			}
    		}
    	}
    	for(int i=1;i<=n;++i){
    		if(!vis[i])continue;
    		if(col[i]<=0)continue;
    		col[vis[i]]=col[i];
    	}
    	for(int i=1;i<=c;++i)sum[1]+=dp[1][i];
    	for(int i=2;i<=n;++i){
    		if(col[i]==0&&!vis[i]){
    			//无限制
    			for(int j=1;j<=c;++j){
    				dp[i][j]*=(sum[i-1]-dp[i-1][j]);
    			}
    		}
    		else if(col[i]==0&&vis[i]){
    
    		}
    	}*/
    	/*if(col[1]==0)for(int i=1;i<=c;++i)dp[1][i]=1;
    	else if(col[1]>0)dp[1][col[1]]=1;
    	else for(int i=1;i<=c;++i){if(i!=-col[1])dp[1][i]=1;}
    	for(int i=2;i<=n;++i){
    		if(vis[i]){
    			if(col[i]==0){
    				for(int j=1;j<=c;++j)dp[i][j]=dp[i-1][j];
    			}
    			else{
    				if(col[i]<0){
    					for(int j=1;j<=c;++j){
    						if(j==-col[i])continue;
    						dp[i][j]=dp[i-1][j];
    					}
    				}
    				else{
    					dp[i][col[i]]=dp[i-1][col[i]];
    				}
    			}
    		}
    		else{
    			//not same&&col is free
    			if(col[i]==0){
    				for(int j=1;j<=c;++j){
    					for(int k=1;k<=c;++k){
    						if(j==k)continue;
    						dp[i][j]+=dp[i-1][k];
    					}
    				}
    				//cout<<"qwq
    ";
    			}
    			else if(col[i]<0){
    				for(int j=1;j<=c;++j){
    					if(j==-col[i])continue;
    					for(int k=1;k<=c;++k){
    						if(j==k)continue;
    						dp[i][j]+=dp[i-1][k];
    					}
    				}
    			}
    			else{
    				for(int j=1;j<=c;++j){
    					if(j==col[i])continue;
    					dp[i][col[i]]+=dp[i-1][j];
    				}
    			}
    		}
    	}*/
    	for(int p=1; p<=c; ++p) {
    		//one's color
    		if(-col[1]==p)continue;
    		for(int i=1; i<=n; ++i)for(int j=1; j<=c; ++j)dp[i][j]=0;//prepare for
    		dp[1][p]=1;//first
    		for(int i=2; i<n; ++i) {
    			
    			for(int j=1; j<=c; ++j) {
    				if(dislike[i][j])continue;
    				if(vis[i]) {
    					dp[i][j]+=dp[i-1][j];
    					dp[i][j]%=mod;
    				} else {
    					for(int k=1; k<=c; ++k) {
    						if(k==j)continue;
    						dp[i][j]+=dp[i-1][k];
    						dp[i][j]%=mod;
    					}
    				}
    			}
    		}
    			for(int i=1; i<=c; ++i) {
    				if(dislike[n][i]||i==p)continue;
    				if(vis[n])dp[n][i]+=dp[n-1][i],dp[n][i]%=mod;
    				else {
    					for(int j=1; j<=c; ++j) {
    						if(i==j)continue;
    						dp[n][i]+=dp[n-1][j];
    						dp[n][i]%=mod;
    					}
    				}
    			}
    		for(int i=1; i<=c; ++i)ans+=dp[n][i],ans%=mod;
    	}
    	printf("%lld
    ",ans%mod);
    	return 0;
    }
    

    注意题目细节,操作(1,2)并不一定只有一个,所以要开一个数组来存储所有不能染的颜色,就是代码中的(dislike[][].)

    看代码中思路不清晰的后果,注释了一大堆,写了一百五十多行……

  • 相关阅读:
    LeetCode 1275. 找出井字棋的获胜者 Find Winner on a Tic Tac Toe Game
    LeetCode 307. 区域和检索
    LeetCode 1271 十六进制魔术数字 Hexspeak
    秋实大哥与花 线段树模板
    AcWing 835. Trie字符串统计
    Leetcode 216. 组合总和 III
    Mybatis 示例之 复杂(complex)属性(property)
    Mybatis 示例之 复杂(complex)属性(property)
    Mybatis 高级结果映射 ResultMap Association Collection
    Mybatis 高级结果映射 ResultMap Association Collection
  • 原文地址:https://www.cnblogs.com/h-lka/p/12821358.html
Copyright © 2011-2022 走看看