Codeforces1594 E2. Rubik‘s Cube Coloring (hard version)(思维+dp记忆化搜索)
Posted live4m
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces1594 E2. Rubik‘s Cube Coloring (hard version)(思维+dp记忆化搜索)相关的知识,希望对你有一定的参考价值。
题意:
解法:
先预处理d[c][k]表示根节点颜色为c,深度为k的满二叉树方案数.
0<=c<6,1<=k<=60,数据范围较小,因此可以很快的预处理.
如果一颗子树,所有点都没有颜色,那么可以用预处理的数组直接O(1)给出方案数.
因此我们只需要关注有带色点的子树.
由于只有2000个点有颜色,k<=60,因此最多2000*60个点是我们需要关注的,
我们对这2000*60个点单独记忆化搜索即可:
令d2[id][c]表示id点颜色为c,子树的方案数,
其中id是点的编号,c是点的颜色.
d[][]和d2[][]的转移:
枚举左右子节点的颜色计算方案数即可.
算法复杂度显然为O(能过).
code:
#include<bits/stdc++.h>
// #define MULTI_CASE
#define SYNC_OFF
#define PI pair<int,int>
#define int long long
using namespace std;
// const int mod=998244353;
const int mod=1e9+7;
const int maxm=2e6+5;
map<int,int>col;
map<int,int>idx;int num;
map<int,bool>mark;//标记子树中至少有一个颜色的点
int lim[10][10];
int d[10][66];
int d2[2222*66][6];
int n,k;
map<char,int>c_mp={
{'w',0},
{'y',1},
{'g',2},
{'b',3},
{'r',4},
{'o',5},
};
/*
0是白 白黄
1是黄 白黄
2是绿 绿蓝
3是蓝 绿蓝
4是红 红橙
5是橙 红橙
*/
void init(){
//初始化lim[][]
lim[0][0]=lim[0][1]=1;
lim[1][0]=lim[1][1]=1;
lim[2][2]=lim[2][3]=1;
lim[3][2]=lim[3][3]=1;
lim[4][4]=lim[4][5]=1;
lim[5][4]=lim[5][5]=1;
}
int dp_dfs(int c,int k){
if(k==1)return 1;
if(d[c][k]!=-1)return d[c][k];
d[c][k]=0;
for(int i=0;i<6;i++){//左边的颜色
if(lim[c][i])continue;
for(int j=0;j<6;j++){//右边的颜色
if(lim[c][j])continue;
d[c][k]=(d[c][k]+dp_dfs(i,k-1)*dp_dfs(j,k-1)%mod)%mod;
}
}
return d[c][k];
}
int dfs(int c,int k,int id){
if(col.count(id)&&col[id]!=c)return 0;//判断合法性
if(k==1)return 1;//最后一层
//如果子树中所有点都没有颜色,那么直接返回预处理的结果
if(!mark.count(id))return d[c][k];
//如果至少有一个子节点有颜色,那么记忆化搜索
if(!idx.count(id))idx[id]=++num;
int x=idx[id];//获取映射后的下标
if(d2[x][c]!=-1)return d2[x][c];
d2[x][c]=0;
int l=id*2,r=id*2+1;
for(int i=0;i<6;i++){//左边的颜色
if(lim[c][i])continue;
for(int j=0;j<6;j++){//右边的颜色
if(lim[c][j])continue;
d2[x][c]=(d2[x][c]+dfs(i,k-1,l)*dfs(j,k-1,r)%mod)%mod;
}
}
return d2[x][c];
}
void solve(){
init();
cin>>k>>n;
//初始化d[][]
memset(d,-1,sizeof d);
memset(d2,-1,sizeof d2);
for(int i=0;i<6;i++){
dp_dfs(i,k);
}
//
for(int i=1;i<=n;i++){
int x;cin>>x;
char s[10];cin>>s;
col[x]=c_mp[s[0]];//点x的颜色
while(x){//O(log)标记所有祖先节点
mark[x]=1;
x/=2;
}
}
int ans=0;
for(int i=0;i<6;i++){
ans=(ans+dfs(i,k,1))%mod;
}
cout<<ans<<endl;
}
void Main(){
#ifdef MULTI_CASE
int T;cin>>T;while(T--)
#endif
solve();
}
void Init(){
#ifdef SYNC_OFF
ios::sync_with_stdio(0);cin.tie(0);
#endif
#ifndef ONLINE_JUDGE
freopen("../in.txt","r",stdin);
freopen("../out.txt","w",stdout);
#endif
}
signed main(){
Init();
Main();
return 0;
}
以上是关于Codeforces1594 E2. Rubik‘s Cube Coloring (hard version)(思维+dp记忆化搜索)的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces - 1594A Consecutive Sum Riddle数学计算
CodeForces - 1594A Consecutive Sum Riddle数学计算
Codeforces1594 F. Ideal Farm(思维,数学)