LINK


题目大意

有一个 n 行 m 列的格点图,你需要给每个点上染上 k 种颜色中的一种,要求没有两个相邻点颜色相同。给定第一行与最后一行的染色,试求总染色方案数。

思路

暴力预处理状态暴力转移可以得到80分的高分

这个时候司来了一句:

不要按行转移,按块转移就A了

于是改改改写了一个轮廓线

就把轮廓线上的颜色信息记录下来就好了,随便转移一下


注意终止状态也需要考虑轮廓线上的情况

需要把最后一个位置的轮廓加上


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
typedef pair<int, int> pi;
typedef long long ll;
typedef double db;
#define fi first
#define se second
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int Mod = 376544743;
const int N = 1e2 + 10;
const int M = 10;
const int K = 1 << (M << 1);
int n, m, k;
int s[(int)1e5 + 10][2]; int add(int a, int b) {
return (a += b) >= Mod ? a - Mod : a;
} int mul(int a, int b) {
return 1ll * a * b % Mod;
} namespace Solve1 {
void solve() {
fu(i, 1, m) Read(s[i][0]);
fu(i, 1, m) Read(s[i][1]);
fu(i, 2, m) {
if (s[i][0] == s[i - 1][0] || s[i][1] == s[i - 1][1]) {
printf("0");
return;
}
}
fu(i, 1, m) {
if (s[i][0] != s[i][1]) {
if (n & 1) {
printf("0");
return;
}
} else {
if (!(n & 1)) {
printf("0");
return;
}
}
}
printf("1");
}
} namespace Solve2 {
vector<int> group;
int dp[N][K];
bool trans[8800][8800];
void dfs(int tmp, int s) {
if (!tmp) {
group.push_back(s);
return;
}
fu(i, 0, k - 1)
if ((s & 3) != i) dfs(tmp - 1, (s << 2) | i);
}
bool check(int s1, int s2) {
fu(i, 1, m) {
if (!((s1 & 3) ^ (s2 & 3))) return 0;
s1 >>= 2;
s2 >>= 2;
}
return 1;
}
void solve() {
fu(i, 1, m) Read(s[i][0]);
fu(i, 1, m) Read(s[i][1]);
int bg = 0, ed = 0;
fu(i, 2, m) {
if (s[i][0] == s[i - 1][0] || s[i][1] == s[i - 1][1]) {
printf("0");
return;
}
}
fu(i, 1, m) {
bg = (bg << 2) + s[i][0];
ed = (ed << 2) + s[i][1];
}
fu(i, 0, k - 1) dfs(m - 1, i);
fv(i, group)
fu(j, 0, i - 1)
if (check(group[i], group[j]))
trans[i][j] = trans[j][i] = 1;
int posbg = 0, posed = 0;
fv(i, group) {
if (group[i] == bg) posbg = i;
if (group[i] == ed) posed = i;
}
dp[1][posbg] = 1;
fu(i, 2, (n >> 1)) {
fv(j, group) if (dp[i - 1][j]) {
fv(k, group) if (trans[j][k]) {
dp[i][k] = add(dp[i][k], dp[i - 1][j]);
}
}
}
dp[n][posed] = 1;
fd(i, n - 1, ((n >> 1) + 1)) {
fv(j, group) if (dp[i + 1][j]) {
fv(k, group) if (trans[j][k]) {
dp[i][k] = add(dp[i][k], dp[i + 1][j]);
}
}
}
int ans = 0;
fv(i, group) if (dp[n >> 1][i])
fv(j, group) if (trans[i][j])
ans = add(ans, mul(dp[n >> 1][i], dp[(n >> 1) + 1][j]));
Write(ans);
}
} namespace Solve3 {
int dp[2][M][K];
void solve() {
fu(i, 1, m) Read(s[i][0]);
fu(i, 1, m) Read(s[i][1]);
int bg = 0, ed = 0, up = (1 << ((m + 1) << 1)) - 1;
fu(i, 2, m) {
if (s[i][0] == s[i - 1][0] || s[i][1] == s[i - 1][1]) {
printf("0");
return;
}
}
fd(i, m, 1) {
bg = (bg << 2) + s[i][0];
ed = (ed << 2) + s[i][1];
}
int ind = 0;
dp[ind][m][bg] = 1;
fu(i, 2, n) {
ind ^= 1;
memset(dp[ind], 0, sizeof(dp[ind]));
fu(s, 0, up) if (dp[ind ^ 1][m][s])
dp[ind][0][(s << 2) & up] = add(dp[ind][0][(s << 2) & up], dp[ind ^ 1][m][s]);
fu(j, 1, m) {
fu(s, 0, up) if (dp[ind][j - 1][s]) {
fu(p, 0, k - 1) if ((((j == 1) || (((s >> ((j - 1) << 1))) & 3) != p) && ((s >> (j << 1)) & 3) != p)) {
int nxt = (s & (up ^ (15 << ((j - 1) << 1)))) | ((p | (p << 2)) << ((j - 1) << 1));
dp[ind][j][nxt] = add(dp[ind][j][nxt], dp[ind][j - 1][s]);
}
}
}
}
Write(dp[ind][m][ed | (s[m][1] << (m << 1))]); // 结束状态不是ed 需要考虑最后的轮廓线状态
}
} int main() {
#ifdef dream_maker
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
Read(n), Read(m), Read(k);
if (k == 2) Solve1::solve();
else if (m <= 0) Solve2::solve();
else Solve3::solve();
return 0;
}

Luogu2435 染色【状压qwq】【轮廓线DP】的更多相关文章

  1. HDU 4336-Card Collector(状压,概率dp)

    题意: 有n种卡片,每包面里面,可能有一张卡片或没有,已知每种卡片在面里出现的概率,求获得n种卡片,需要吃面的包数的期望 分析: n很小,用状压,以前做状压时做过这道题,但概率怎么推的不清楚,现在看来 ...

  2. CF1238E.Keyboard Purchase 题解 状压/子集划分DP

    作者:zifeiy 标签:状压DP,子集划分DP 题目链接:https://codeforces.com/contest/1238/problem/E 题目大意: 给你一个长度为 \(n(n \le ...

  3. P4547 [THUWC2017]随机二分图(状压,期望DP)

    期望好题. 发现 \(n\) 非常小,应该要想到状压的. 我们可以先只考虑 0 操作. 最难的还是状态: 我们用 \(S\) 表示左部点有哪些点已经有对应点, \(T\) 表示右部点有哪些点已经有对应 ...

  4. UVA 11600-Masud Rana(状压,概率dp)

    题意: 有n个节点的图,开始有一些边存在,现在每天任意选择两点连一条边(可能已经连过),求使整个图联通的期望天数. 分析: 由于开始图可以看做几个连通分量,想到了以前做的一个题,一个点代表一个集合(这 ...

  5. UVA - 10817 Headmaster's Headache (状压类背包dp+三进制编码)

    题目链接 题目大意:有S门课程,N名在职教师和M名求职者,每名在职教师或求职者都有自己能教的课程集合以及工资,要求花费尽量少的钱选择一些人,使得每门课程都有至少两人教.在职教师必须选. 可以把“每个课 ...

  6. CF1556F Sports Betting (状压枚举子集DP)

    F 对于一张比赛图,经过缩点,会得到dag,且它一定是transitive的,因此我们能直接把比赛图缩成一个有向链.链头作为一个强连通分量,里面的所有点都是胜利的 定义F(win)表示win集合作为赢 ...

  7. UVALive 6912 Prime Switch 状压DP

    Prime Switch 题目连接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8& ...

  8. HDU 4336 Card Collector 期望dp+状压

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4336 Card Collector Time Limit: 2000/1000 MS (Java/O ...

  9. Codeforces ----- Kefa and Dishes [状压dp]

    题目传送门:580D 题目大意:给你n道菜以及每道菜一个权值,k个条件,即第y道菜在第x道后马上吃有z的附加值,求从中取m道菜的最大权值 看到这道题,我们会想到去枚举,但是很显然这是会超时的,再一看数 ...

随机推荐

  1. Java基础反射(二)

    原文地址http://blog.csdn.net/sinat_38259539/article/details/71799078 反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Cla ...

  2. CCPC-Wannafly Winter Camp Day1 (Div2, onsite)

    Replay Dup4: 要是不挂机,再多仔细想想就好了 J确实自闭好久,一直在想正确性,最后数据错了,喵喵喵? 还是要保证充足的休息啊,中间睡了一小会儿,也不知道睡了多久,醒来他们就又过了一道 要发 ...

  3. 对java沙箱机制的一点了解

    1.   引入 我们都知道,程序员编写一个Java程序,默认的情况下可以访问该机器的任意资源,比如读取,删除一些文件或者网络操作等.当你把程序部署到正式的服务器上,系统管理员要为服务器的安全承担责任, ...

  4. CSS实现超出DIV宽度文字自动隐藏并显示省略号

    当文字超出DIV宽度时,超出的文字部分省略,并用显示省略号代替,css代码如下: div.ellipsis { padding-left: 5px; text-align: left; text-ov ...

  5. MySQL "Zero date value prohibited" 问题解析

    问题起因 之前一直使用Oracle数据,对MySQL数据库使用不多,因此搞不懂MySQL的日期“0000-00-00 00:00:00”对程序会产生怎样的影响.费了我一下午的时间 -_-^^. 首先: ...

  6. Kali2018.1

    目录 制作U盘启动盘 安装 Kali Linux 之后的事 更新源 配置 Zsh 配置 Vim 修改 Firefox 语言为中文 安装 Gnome 扩展 美化 安装 Google 拼音输入法 安装常用 ...

  7. Tomcat灵活配置多项目,多端口,多域名,多虚拟目录

    Tomcat的配置都在Tomcat的安装目录的conf文件夹下的server.xml文件 最初内容:(去掉所有注释) <?xml version="1.0" encoding ...

  8. 斜率优化DP学习笔记

    先摆上学习的文章: orzzz:斜率优化dp学习 Accept:斜率优化DP 感谢dalao们的讲解,还是十分清晰的 斜率优化$DP$的本质是,通过转移的一些性质,避免枚举地得到最优转移 经典题:HD ...

  9. ZOJ 3769 Diablo III(分组背包)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3769 题意:有13种装备,每种装备值可以穿戴一种,特殊的就是双手武器和单手 ...

  10. HDU 3435 A new Graph Game(最小费用流:有向环权值最小覆盖)

    http://acm.hdu.edu.cn/showproblem.php?pid=3435 题意:有n个点和m条边,你可以删去任意条边,使得所有点在一个哈密顿路径上,路径的权值得最小. 思路: 费用 ...