题目

有n个木块排成一行,从左到右依次编号为1~n。你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块。

所有油漆刚好足够涂满所有木块,即c1+c2+…+ck=n。相邻两个木块涂相同色显得很难看,所以你希望统计任意两

个相邻木块颜色不同的着色方案。

输入格式

第一行为一个正整数k,第二行包含k个整数c1, c2, … , ck。

输出格式

输出一个整数,即方案总数模1,000,000,007的结果。

输入样例

3

1 2 3

输出样例

10

提示

100%的数据满足:1 <= k <= 15, 1 <= ci <= 5

题解

乍一看还以为是普通的dp,发现颜色次数限制还真不好整。

但不同颜色是没有什么区别的【只在与上一个颜色冲不冲突的问题上有区别】

观察颜色使用次数很少,我们尝试不用颜色作为状态,用所剩次数作为状态

设f[a][b][c][d][e][k]表示可用1次的颜色有a个,可用2次的颜色有b个,可用3次的颜色有c个,可用4次的颜色有d个,可用5次的颜色有e个,上一次使用的颜色为当前还剩k个的颜色

那么状态转移时我们就可以枚举这次涂上哪一个

比如涂上可用3次的颜色,那么就有c∗f[a][b+1][c−1][d][e]种方案,如果k==c,那么只有(c−1)∗f[a][b+1][c−1][d][e]种,因为c种颜色中有一种上一次涂上了

其它也是类似的。

用记忆化搜索会好写一些

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)
using namespace std;
const int maxn = 105,maxm = 16,INF = 1000000000,P = 1000000007;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int N = 0,K,s[maxn];
LL f[maxm][maxm][maxm][maxm][maxm][6];
bool vis[maxm][maxm][maxm][maxm][maxm][6];
LL dp(int a,int b,int c,int d,int e,int k){
LL t = 0;
if (vis[a][b][c][d][e][k]) return f[a][b][c][d][e][k];
if (a + b + c + d + e == 0) return 1;
if (a) t = (t + (LL)(a - (k == 2)) * dp(a - 1,b,c,d,e,1)) % P;
if (b) t = (t + (LL)(b - (k == 3)) * dp(a + 1,b - 1,c,d,e,2)) % P;
if (c) t = (t + (LL)(c - (k == 4)) * dp(a,b + 1,c - 1,d,e,3)) % P;
if (d) t = (t + (LL)(d - (k == 5)) * dp(a,b,c + 1,d - 1,e,4)) % P;
if (e) t = (t + (LL)e * dp(a,b,c,d + 1,e - 1,5)) % P;
vis[a][b][c][d][e][k] = true;
return f[a][b][c][d][e][k] = t;
}
int main(){
K = RD();
REP(i,K) s[RD()]++;
printf("%lld\n",dp(s[1],s[2],s[3],s[4],s[5],0));
return 0;
}

BZOJ1079 [SCOI2008]着色方案 【dp记忆化搜索】的更多相关文章

  1. bzoj 1079: [SCOI2008]着色方案【记忆化搜索】

    本来打算把每个颜色剩下的压起来存map来记忆化,写一半发现自己zz了 考虑当前都能涂x次的油漆本质是一样的. 直接存五个变量分别是剩下12345个格子的油漆数,然后直接开数组把这个和步数存起来,记忆化 ...

  2. 【P2476】着色方案(记忆化搜索+特殊的DP数组)

    这个题代码难度几乎为0,然而思维难度对于蒟蒻来说简直是突破天际啊!首先我思考的是这个油漆的种类只有15种,是不是可以像一道叫做8数码难题的东西暴力15维数组呢..计算发现不可以....空间会直接让你学 ...

  3. BZOJ1079:[SCOI2008]着色方案(DP)

    Description 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n.相邻两个 ...

  4. 【bzoj5123】[Lydsy12月赛]线段树的匹配 树形dp+记忆化搜索

    题目描述 求一棵 $[1,n]$ 的线段树的最大匹配数目与方案数. $n\le 10^{18}$ 题解 树形dp+记忆化搜索 设 $f[l][r]$ 表示根节点为 $[l,r]$ 的线段树,匹配选择根 ...

  5. ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. Poor Ramzi -dp+记忆化搜索

    ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. ...

  6. 【BZOJ】1415 [Noi2005]聪聪和可可 期望DP+记忆化搜索

    [题意]给定无向图,聪聪和可可各自位于一点,可可每单位时间随机向周围走一步或停留,聪聪每单位时间追两步(先走),问追到可可的期望时间.n<=1000. [算法]期望DP+记忆化搜索 [题解]首先 ...

  7. [题解](树形dp/记忆化搜索)luogu_P1040_加分二叉树

    树形dp/记忆化搜索 首先可以看出树形dp,因为第一个问题并不需要知道子树的样子, 然而第二个输出前序遍历,必须知道每个子树的根节点,需要在树形dp过程中记录,递归输出 那么如何求最大加分树——根据中 ...

  8. poj1664 dp记忆化搜索

    http://poj.org/problem?id=1664 Description 把M个相同的苹果放在N个相同的盘子里,同意有的盘子空着不放,问共同拥有多少种不同的分法?(用K表示)5.1.1和1 ...

  9. 状压DP+记忆化搜索 UVA 1252 Twenty Questions

    题目传送门 /* 题意:给出一系列的01字符串,问最少要问几个问题(列)能把它们区分出来 状态DP+记忆化搜索:dp[s1][s2]表示问题集合为s1.答案对错集合为s2时,还要问几次才能区分出来 若 ...

  10. POJ 1088 DP=记忆化搜索

    话说DP=记忆化搜索这句话真不是虚的. 面对这道题目,题意很简单,但是DP的时候,方向分为四个,这个时候用递推就好难写了,你很难得到当前状态的前一个真实状态,这个时候记忆化搜索就派上用场啦! 通过对四 ...

随机推荐

  1. spring-传统AOP

    Spring传统AOP AOP的增强类型 AOP联盟定义了Advice(org.aopalliance.aop.Interface.Advice) 五类(目标类方法的连接点): 1.  前置通知(or ...

  2. tomcat日志切割脚本

    tomcat日志每俩小时切割的脚本如下(这是用定时任务来完成的,此方法无需重启tomcat): time=$(date +%H) end_time=`` a=$end_time BF_TIME=$(- ...

  3. http协议组成(请求状态码)

    http请求由:请求行:消息报头:请求正文组成 //请求行 Request URL: http://172.32.4.33:8080/operation/v2/autoServer/queryAuto ...

  4. yii2深入理解之内核解析

    一.前言 首先,yii2最为为数不多的PHP主流开源框架,受欢迎程度不亚于laravel和TP.个人认为,研究这些框架底层代码是非常有助于自身代码编程思想的提升和代码简化程度和质量的提升的. 那么,话 ...

  5. Python基础-字符串的使用

    基础知识 字符串解释:字符串是不可变的,所有元素赋值和切片赋值操作都是非法的,属于序列一种(字符串.元组.列表). 一.格式化字符串 (1).format()方法==str.format() 作用:将 ...

  6. 找回被丢弃怎么找都找不回来的git中的commit

    崩溃的一天,打算提代码走人,结果切分支之后,commit丢了= =,找了三个多小时 接下来分享下如何找回丢失的commit的 打开项目所在位置,打开git bash,在gitBASH中输入 git f ...

  7. [Bzoj3611]大工程(虚树+DP)

    Description 题目链接 Solution 在虚树上跑DP即可 关于虚树的建立,是维护一个最右链的过程 关键代码如下: sort(A+1,A+k+1,cmp);//按dfs序排序 s[top= ...

  8. android 文件下载 超简单

    public void downloadPlug(String downloadUrl,String savePath) { try { URL url = new URL(downloadUrl); ...

  9. 如何使用Idea导入jar包

    技术交流群: 233513714 1.在idea底部找到Terminal,然后进入输入框,如下图所示 2.在输入框中输入 mvn install:install-file -D file=C:\Use ...

  10. 直接插入排序&希尔排序

    1.直接插入排序 时间复杂度O(n2) 工作原理: 通过构建有序序列,对于未排序数据,在已排序的序列中,从后向前扫描,找到相应的位置并插入. 插入排序在实现上,在从后向前扫描的过程中,需要反复把已排序 ...