1079: [SCOI2008]着色方案

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2237  Solved: 1361
[Submit][Status][Discuss]

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

  这道题挺有趣的,他将DP与记忆化搜索结合在了一起……
  我们做一个假设,假设ci都为1,那么这就是一道状压题了,但是ci<=5,虽然仍然不大,但是状压15位显然扑街。
  让我们回过头在看最基础的暴力,也就是我们去枚举每一位放的颜色,并将它传递给下一层dfs,如果我们分析一下的话我们会发现每一种剩下可涂数量相同的颜色都可以看作等价的,换句话说涂谁都行。那么,我们将状压的方式换一换,不对,不能叫状压了。改为ci剩余1 2 3 4 5 个的颜色有几种,上一个是谁,也就是f[15][15][15][15][15][7]。空间没问题,至于转移,我们利用dfs的思想,使用记忆化搜索,然后对于每一个f,假设当前状态为f[a][b][c][d][e][la]
  则若d!=0且la!=3那么f[a][b][c][d][e][la]+=f[a][b][c][d-1][e+1][2]*d。
  若la=3那么f[a][b][c][d][e][la]+=(d-1)*f[a][b][c][d-1][e+1][2]。
  其余同理。
  不得不说转移数组挺像一道概率DP“抵制克苏恩”的,可惜没有能够应用到这道题来啊。
 #include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
int n,t,a[],js[];
long long f[][][][][][],p=;
bool vi[][][][][][];
long long dfs(int a,int b,int c,int d,int e,int la)
{
     
    if(a==&&b==&&c==&&d==&&e==)return ;
    if(vi[a][b][c][d][e][la])return f[a][b][c][d][e][la];
    vi[a][b][c][d][e][la]=;
    if(a)f[a][b][c][d][e][la]+=a*dfs(a-,b+,c,d,e,),f[a][b][c][d][e][la]%=p;
    if(b)
    {
        if(b!=)f[a][b][c][d][e][la]+=(b-(la==))*dfs(a,b-,c+,d,e,);
        else if(la!=)f[a][b][c][d][e][la]+=dfs(a,b-,c+,d,e,);
        f[a][b][c][d][e][la]%=p;
    }
    if(c)
    {
        //cout<<a<<' '<<b<<' '<<c<<' '<<d<<' '<<e<<endl;
        if(c!=)f[a][b][c][d][e][la]+=(c-(la==))*dfs(a,b,c-,d+,e,);
        else if(la!=) f[a][b][c][d][e][la]+=dfs(a,b,c-,d+,e,);
        f[a][b][c][d][e][la]%=p;
    }
    if(d)
    {
         
        if(d!=)f[a][b][c][d][e][la]+=(d-(la==))*dfs(a,b,c,d-,e+,);
        else if(la!=)f[a][b][c][d][e][la]+=dfs(a,b,c,d-,e+,);
        f[a][b][c][d][e][la]%=p;
    }
    if(e)
    {
        if(e!=)f[a][b][c][d][e][la]+=(e-(la==))*dfs(a,b,c,d,e-,);
        else if(la!=)f[a][b][c][d][e][la]+=dfs(a,b,c,d,e-,);
        f[a][b][c][d][e][la]%=p;
    }
    return f[a][b][c][d][e][la];
}
int main()
{
    scanf("%d",&t);
    for(int i=;i<=t;i++)
    {
        scanf("%d",&a[i]);
        n+=a[i];
        js[a[i]]++;
    }
    long long ans=dfs(js[],js[],js[],js[],js[],);
    printf("%lld\n",ans);
    return ;
}

  顺便提一句,我之所以还要多开一个vi数组,是为了防止f模p之后为0的情况。

Bzoj 1079 着色方案 题解的更多相关文章

  1. [BZOJ]1079 着色方案(SCOI2008)

    相邻色块不同的着色方案,似乎这道题已经见过3个版本了. Description 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块.所有油漆刚好足够 ...

  2. bzoj 1079 着色方案

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

  3. BZOJ 1079 着色方案(DP)

    如果把当前格子涂什么颜色当做转移的话,状态则是每个格子的颜色数还剩多少,以及上一步用了什么颜色,这样的状态量显然是5^15.不可取. 如果把当前格子涂颜色数还剩几个的颜色作为转移的话,状态则是每个格子 ...

  4. BZOJ 1079: [SCOI2008]着色方案 记忆化搜索

    1079: [SCOI2008]着色方案 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...

  5. BZOJ 1079: [SCOI2008]着色方案(巧妙的dp)

    BZOJ 1079: [SCOI2008]着色方案(巧妙的dp) 题意:有\(n\)个木块排成一行,从左到右依次编号为\(1\)~\(n\).你有\(k\)种颜色的油漆,其中第\(i\)种颜色的油漆足 ...

  6. [BZOJ 1079][SCOI 2008]着色方案

    1079: [SCOI2008]着色方案 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2237  Solved: 1361[Submit][Stat ...

  7. bzoj 1079: [SCOI2008]着色方案 DP

    1079: [SCOI2008]着色方案 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 803  Solved: 512[Submit][Status ...

  8. 【BZOJ】1079: [SCOI2008]着色方案(dp+特殊的技巧)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1079 只能想到5^15的做法...........................果然我太弱. 其实 ...

  9. 【BZOJ 1079】[SCOI2008]着色方案

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

随机推荐

  1. [WPF疑难] 如何限定ListView列宽度

    原文:[WPF疑难] 如何限定ListView列宽度 [WPF疑难] 如何限定ListView列宽度                                            周银辉 今天 ...

  2. vs调试cordova app时 scriptedsandbox64.exe已停止工作的错误处理方法

    1.把ie更新到版本11 2.去掉 选项->调试->调试时启动诊断工具 有时候调试会启动失败,提示版本过低,再一次点击调试就可以了.

  3. c#实现golang 的channel

    使用.NET的 BlockingCollection<T>来包装一个ConcurrentQueue<T>来实现golang的channel. 代码如下: public clas ...

  4. Tensorflow数据读取机制

    展示如何将数据输入到计算图中 Dataset可以看作是相同类型"元素"的有序列表,在实际使用时,单个元素可以是向量.字符串.图片甚至是tuple或dict. 数据集对象实例化: d ...

  5. delphi7 stringgrid 点列头排序

    最近在做stringgrid的项目, 下面delphi7 正常使用,均摘抄网路,但做过细微调整才能正常使用 首先排序的过程 procedure Quicksort(Grid: TStringGrid; ...

  6. 21 步助你成为成功的 Web 开发者(激情不是被动的:它是一种对行动起来的追求)

    随着 Web 开发产业的爆发式发展,许多人会问这样的问题:我如何才能成为一名 Web 开发者?我认为这是一个错误的提问.问题应该是:我如何才能成为一名成功的 Web 开发者? 能提出这样的问题很重要, ...

  7. 注册表Demo

    一.获取安装程序信息 #include <windows.h> #include <iostream> #include <string> #include < ...

  8. Linux中同步互斥机制研究之原子操作

    操作系统中,对共享资源的访问需要有同步互斥机制来保证其逻辑的正确性,而这一切的基础便是原子操作. | 原子操作(Atomic Operations):    原子操作从定义上理解,应当是类似原子的,不 ...

  9. Hadoop集群(第5期)SecureCRT使用

    1.SecureCRT简介   SecureCRT是一款支持SSH(SSH1和SSH2)的终端仿真程序,同时支持Telnet和rlogin协议.SecureCRT是一款用于连接运行包括Windows. ...

  10. shell多线程

    a='a1' b='b1' c='c1' d='d1' e='e1' ARR=($a $b $c $d $e) rd=`date +%N` for i in ${ARR[*]} do { ;>& ...