涂抹果酱
N行M列蛋糕,3种果酱;相邻不能同色;第K行
正文
/*
原题:T1594 「一本通 5.4 练习 1」涂抹果酱 (TYVJ)
题意:N 行 M 列(M≤5)蛋糕,3 种果酱(1/2/3);相邻(上下左右)不能同色;第 K 行已固定,求方案数 mod 10^6。
思路:按列状压(M≤5)。先枚举所有合法单行方案(行内相邻列颜色不同),再要求相邻两行同列颜色不同。
以第 K 行为强制状态做逐行 DP:dp[i][p] 为前 i 行以方案 p 结尾的方案数,p 与上一行逐列不同。
复杂度:时间 O(N·S²),空间 O(S),S≤3^M(M=5 时 S≤243,实际合法单行 ≤48)。
易错点:1) 取模为 10^6;
2) 第 K 行给定方案本身必须合法,否则直接输出 0;
3) 仅 4-邻接不同色,不含对角与“连续三个同色”。
*/
#include <bits/stdc++.h>
using namespace std;
const int MOD=1000000;
int main(){
int N,M,K;
if(!(cin>>N>>M>>K)) return 0;
vector<int> fixedRow(M);
for(int j=0;j<M;j++) cin>>fixedRow[j];
// 枚举所有合法单行方案:相邻列颜色不同(颜色编码为 0/1/2)
vector<int> pat; // 每行方案的整数编码
vector<vector<int>> col; // 每方案各列颜色
int total=1;
for(int i=0;i<M;i++) total*=3;
for(int code=0;code<total;code++){
int c=code;
bool okp=true;
vector<int> tmp(M);
for(int j=M-1;j>=0;j--){ tmp[j]=c%3; c/=3; }
for(int j=0;j+1<M;j++) if(tmp[j]==tmp[j+1]){ okp=false; break; }
if(okp){ pat.push_back(code); col.push_back(tmp); }
}
int S=pat.size();
// 单行间兼容性:同列颜色必须不同
vector<vector<bool>> compat(S,vector<bool>(S,false));
for(int i=0;i<S;i++) for(int j=0;j<S;j++){
bool okc=true;
for(int c2=0;c2<M;c2++) if(col[i][c2]==col[j][c2]){ okc=false; break; }
compat[i][j]=okc;
}
// 定位第 K 行给定方案的编码
int givencode=0;
for(int j=0;j<M;j++) givencode=givencode*3+(fixedRow[j]-1);
int gidx=-1;
for(int i=0;i<S;i++) if(pat[i]==givencode){ gidx=i; break; }
if(gidx<0){ cout<<0<<"\n"; return 0; }
// dp:用前一行的方案集合,并引入“空状态” S 表示第 0 行之前(与任意方案兼容)
vector<long long> prev(S+1,0);
prev[S]=1;
for(int r=1;r<=N;r++){
vector<long long> cur(S+1,0);
if(r==K){
long long sum=0;
for(int q=0;q<=S;q++) if(prev[q]>0){
if(q==S || compat[gidx][q]) sum=(sum+prev[q])%MOD;
}
cur[gidx]=sum;
}else{
for(int p=0;p<S;p++){
long long sum=0;
for(int q=0;q<=S;q++) if(prev[q]>0){
if(q==S || compat[p][q]) sum=(sum+prev[q])%MOD;
}
cur[p]=sum;
}
}
prev=move(cur);
}
long long ans=0;
for(int p=0;p<S;p++) ans=(ans+prev[p])%MOD;
cout<<ans<<"\n";
return 0;
}
一本通·提高篇的其它内容
- 活动安排
- 种树
- 喷水装置
- 加工生产调度
- 智力大冲浪
- 数列极差
- 数列分段
- 线段
- 家庭作业
- 钓鱼
- 糖果传递
- 愤怒的牛
- Best Cow Fences
- 曲线
- 数列分段 II
- 扩散
- 灯泡
- 传送带
- 数的划分
- 生日蛋糕
- 小木棍
- Addition Chains
- 埃及分数
- 平板涂色
- 质数方阵
- 靶形数独
- 电路维修
- 魔板
- Knight Moves
- 棋盘游戏
- Keyboarding
- 移动玩具
- 山峰和山谷
- Oulipo
- 图书管理
- Power Strings
- Seekthe Name, Seek the Fame
- Friends
- A Horrible Poem
- Beads
- Antisymmetry
- 门票
- 收集雪花
- 剪花布条
- Power Strings
- Radio Transmission
- OKR-Periods of Words
- 似乎在梦中见过的样子
- Censoring
- Phone List
- The XOR Largest Pair
- Nikitosh 和异或
- Immediate Decodability
- L 语言
- Secret Message 秘密信息
- 背单词
- The Xor-longest Path
- Keywords Search
- 玄武密码
- Censoring