【BZOJ1079】【SCOI2008】着色方案
Time Limit: 10 Sec Memory Limit: 162 MB
Description
有n个木块排成一行,从左到右依次编号为1~n。你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块。
所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n。相邻两个木块涂相同色显得很难看,所以你希望统计任意两
个相邻木块颜色不同的着色方案。
Input
第一行为一个正整数k,第二行包含k个整数c1, c2, ... , ck。
Output
输出一个整数,即方案总数模1,000,000,007的结果。
Sample Input
3
1 2 3
Sample Output
10
HINT
100%的数据满足:1 <= k <= 15, 1 <= ci <= 5
Solution
是不是还想状压啊,行不通的,状态数太多了。
看看还有什么是比较小的:\(c_i\)看起来很小。
仔细想一想会发现,如果两种颜料的可使用次数相同,那么它们可以归为一类颜料。
从可使用次数分类入手,设状态\(f[a_1][a_2][a_3][a_4][a_5][x]\),表示当前已使用\(i\)次的颜料有\(a_i\)种,且下一步将要选择当前可使用\(x\)次的颜料,的总方案数。
干脆就自顶向下使用记忆化搜索DP实现。每个状态从哪里转移就很显然了:可以挑5类颜料中的一种,那么转移的来源就是\(\{a_1-1,a_2,a_3,a_4,a_5\}\),\(\{a_1+1,a_2-1,a_3,a_4,a_5\}\),\(\{a_1,a_2+1,a_3-1,a_4,a_5\}\),\(\{a_1,a_2,a_3+1,a_4-1,a_5\}\),\(\{a_1,a_2,a_3,a_4+1,a_5-1\}\)。
关键是转移的系数和递归参数。简单的讲,每类颜料\(i\)有\(a_i\)种不同的选法,但这没有考虑到题目要求两两不同给的限制。
注意每个状态的\(a_i\)是相对于当前状态下的信息,而\(x\)则是上一层状态给你做出的限制。你枚举当前这一步将要挑哪一类颜料,递归的时候就要把这类颜料作为下一步的\(x\)传进去,表示你下一层自己选择的时候,如果要选我这一层选择的这类颜料,你可用的选择数必须减1,否则将会和我冲突。而上一层递归给这一层传进了\(x\),说明上一层递归所挑的颜料在上一层为第\(x\)类,那么在这一层则是第\(x-1\)类(没用之前即减1)。如果你枚举当前层选择了第\(x-1\)类颜料,可用方案数必须减1。
需要梳理一下思路和控制关系,实现起来并不难。
#include <cstdio>
#include <cstring>
using namespace std;
const int N=16,MOD=1e9+7;
int n,a[6],c[6];
int f[N][N][N][N][N][6];
int dfs(int a1,int a2,int a3,int a4,int a5,int x){
int &F=f[a1][a2][a3][a4][a5][x];
if(F!=-1) return F;
F=0;
if(a1)
(F+=1LL*dfs(a1-1,a2,a3,a4,a5,1)*(a1-(x-1==1))%MOD)%=MOD;
if(a2)
(F+=1LL*dfs(a1+1,a2-1,a3,a4,a5,2)*(a2-(x-1==2))%MOD)%=MOD;
if(a3)
(F+=1LL*dfs(a1,a2+1,a3-1,a4,a5,3)*(a3-(x-1==3))%MOD)%=MOD;
if(a4)
(F+=1LL*dfs(a1,a2,a3+1,a4-1,a5,4)*(a4-(x-1==4))%MOD)%=MOD;
if(a5)
(F+=1LL*dfs(a1,a2,a3,a4+1,a5-1,5)*a5%MOD)%=MOD;
return F;
}
int main(){
freopen("input.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
c[x]++;
}
memset(f,-1,sizeof f);
for(int i=0;i<=5;i++)
f[0][0][0][0][0][i]=1;
printf("%d\n",dfs(c[1],c[2],c[3],c[4],c[5],0));
return 0;
}
【BZOJ1079】【SCOI2008】着色方案的更多相关文章
- BZOJ1079 [SCOI2008]着色方案 动态规划
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1079 题目概括 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的 ...
- [luogu2476][bzoj1079][SCOI2008]着色方案【动态规划】
题目描述 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块.所有油漆刚好足够涂满所有木块,即c1+c2+-+ck=n.相邻两个木块涂相同色显得很难 ...
- BZOJ1079:[SCOI2008]着色方案(DP)
Description 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n.相邻两个 ...
- BZOJ1079 [SCOI2008]着色方案 【dp记忆化搜索】
题目 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+-+ck=n.相邻两个木块涂相同色显得很难看 ...
- BZOJ1079: [SCOI2008]着色方案 (记忆化搜索)
题意:有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n.相邻两个木块涂相同色显得很 ...
- 2018.10.20 bzoj1079: [SCOI2008]着色方案(多维dp)
传送门 dp妙题. f[a][b][c][d][e][last]f[a][b][c][d][e][last]f[a][b][c][d][e][last]表示还剩下aaa个可以用一次的,还剩下bbb个可 ...
- BZOJ1079 [SCOI2008]着色方案[组合计数DP]
$有a_{1}个1,a_{2}个2,...,a_{n}个n(n<=15,a_{n}<=5),求排成一列相邻位不相同的方案数.$ 关于这题的教训记录: 学会对于复杂的影响分开计,善于发现整体 ...
- bzoj1079: [SCOI2008]着色方案
dp.以上次染色时用的颜色的数量和每种数量所含有的颜色作状态. #include<cstdio> #include<algorithm> #include<cstring ...
- 【记忆化搜索】bzoj1079 [SCOI2008]着色方案
#include<cstring> #include<cstdio> using namespace std; #define MOD 1000000007 typedef l ...
- bzoj1079: [SCOI2008]着色方案
ci<=5直接想到的就是5维dp了...dp方程YY起来很好玩...写成记忆化搜索比较容易 #include<cstdio> #include<cstring> #inc ...
随机推荐
- egret性能优化总结
## 来自官方的优化建议 详见:http://edn.egret.com/cn/article/index/id/287 (1) 少使用Alpha混合. (2) 显式停止计时器,让它们准备好进行垃圾回 ...
- 2018NOIP爆0记第一弹
初赛篇 选择即王道 迪杰斯特拉那道题的A选项自己yy一下觉得甚是不妥,就没选 就和30分完美选择题擦肩而过. 填空最后一题不太会搞,就跳过了,最后蒙了个512上去...其实还有点接近的... 5分 然 ...
- Django FBV/CBV、中间件、GIT使用
s5day82 内容回顾: 1. Http请求本质 Django程序:socket服务端 a. 服务端监听IP和端口 c. 接受请求 \r\n\r\n:请求头和请求体 \r\n & reque ...
- sar命令详解
基础命令学习目录首页 原文链接:http://lovesoo.org/linux-sar-command-detailed.html sar(System Activity Reporter系统活动情 ...
- PHP--面向对象的设计原则
三大特性是:封装.继承.多态 所谓封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏. 封装是面向对象的特征之一,是对象和类概念的主要特 ...
- Task 6.3 冲刺Two之站立会议2
今天主要将聊天的主界面加以改善,添加了用户登陆后的提示,实现了好友的增删和查询以及自己的账号的个人信息,也可以使用户实现对自己的头像以及个性签名.个人信息等的管理.
- beat冲刺(6/7)
目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:beta冲刺(6/7) 团队部分 后敬甲(组长) 过去两天完成了哪些任务 ppt制作 视频拍摄 接下来的计划 准备答辩 ...
- 图论 Kruskal算法 并查集
#include<iostream> #include<cstring> #include<string> #include<cstdio> #incl ...
- 用JAVA制作微型操作系统4月23日情况
弄好了一个自认为十分精美的界面,但本想着昨天就在开始按钮上先套入控制jp222面板上的jb2标签上的时间更新,这按钮起到开始线程的作用(我认为按钮应该可以通过t.start()来触发线程,结果不知为什 ...
- Python开发【第五篇】迭代器、生成器、递归函数、二分法
阅读目录 一.迭代器 1. 迭代的概念 #迭代器即迭代的工具(自定义的函数),那什么是迭代呢? #迭代:指一个重复的过程,每次重复都可以称之为一次迭代,并且每一次重复的结果是下一个迭代的初始值(例如: ...