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. layabox pc app web同步发布的工具

    http://layabox.com/ 或者vs + unity3d开发游戏

  2. C语言实现的CRC16/CCITT-FALSE校验码函数

    要求:输入字符串“00 AA FF CC AA 01 00” 得到校验码“79B1” 方法1: // ConsoleApplication1.cpp: 定义控制台应用程序的入口点. // #inclu ...

  3. 使用Newtonsoft.Json输出JSON

    安装: Install-Package Newtonsoft.Json 代码: //序列化DataTable DataTable dt = new DataTable(); dt.Columns.Ad ...

  4. Android动画基础——属性动画(Property Animation)

    本篇涉及例子下载:Github 本篇讲android 3.0引入的属性动画框架,上篇写视图动画View Animation时就说过ViewAnimation的缺点,那就是动画作用的是view本身的视觉 ...

  5. .NET DataTable转换为JSON格式的字符串

    在进行数据传递的时候,有时我们需要通过Ajax的方式或者其他的方式传递一个数据列表,可以将DataTable或者其他形式的数据列表转换为JSON的格式,通过Ajax实体的形式进行传递. 比如说: // ...

  6. ASP.NET WebForm项目--页面正确返回404及500等状态

    实现方法 项目路径 <system.webServer> <httpErrors errorMode="Custom" > <remove statu ...

  7. CopyMemory、FillMemory、MoveMemory、ZeroMemory

    CopyMemory 复制内存,第一个参数为目的地址,第二个参数为源地址,第三个参数为复制数据的大小,单位字节,源内存区域不能重叠,如果重叠,可以使用MoveMemory()函数.函数原型如下: vo ...

  8. Jetbrains 工具集

    http://www.jetbrains.com/ PRODUCTS IntelliJ IDEA ReSharper WebStorm PhpStorm PyCharm RubyMine AppCod ...

  9. Memory Ordering (注意Cache带来的副作用,每个CPU都有自己的Cache,内存读写不再一定需要真的作内存访问)

    Memory Ordering   Background 很久很久很久以前,CPU忠厚老实,一条一条指令的执行我们给它的程序,规规矩矩的进行计算和内存的存取. 很久很久以前, CPU学会了Out-Of ...

  10. 关于Windows更新窗口内容的问题(作为一个实验,效果很明显)

    Windows中的窗口在特定情况下会由系统进行重绘,如无效区域重新显现时,,会向窗口的处理过程发送VM_PAINT消息,但是,可能还有Windows自己的更新窗口处理,如在下面的代码中,将击键显式地转 ...