zoukankan      html  css  js  c++  java
  • 记忆化搜索 [SCOI2008]着色方案

    问题 B: [SCOI2008]着色方案
    时间限制: 1 Sec 内存限制: 162 MB
    提交: 80 解决: 38
    [提交][状态][讨论版]
    题目描述
    有n个木块排成一行,从左到右依次编号为1~n。你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块。
    所有油漆刚好足够涂满所有木块,即c1+c2+…+ck=n。相邻两个木块涂相同色显得很难看,所以你希望统计任意两
    个相邻木块颜色不同的着色方案。

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

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

    样例输入
    3
    1 2 3
    样例输出
    10

    我们可以发现,可用剩余次数相同的颜色并没必要区别它们,直接记录还有多少种就行了。因此,我们每使用一种颜色,此剩余使用数量的颜色减一,使用数量减一的颜色种数加一。那么方案数+=此次数颜色数量×修改之后的方案总数。但考虑颜色不能连续,搜的时候判断就行了,如果是同一种剩余次数的颜色,-1就行了。
    而且颜色很少?使用次数最大为5?可以开个6维数组记录各剩下多少和上一个是什么就行了。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<iostream>
    #define mod 1000000007
    #define ll long long
    using namespace std;
    int k,a[6];ll f[16][16][16][16][16][6];
    ll dfs(int a1,int a2,int a3,int a4,int a5,int las)
    {
        if((a1|a2|a3|a4|a5)==0)return f[a1][a2][a3][a4][a5][las]=1;
        if(f[a1][a2][a3][a4][a5][las])return f[a1][a2][a3][a4][a5][las];
        ll s=0;
        if(a1)s+=(a1-(las==2))*dfs(a1-1,a2,a3,a4,a5,1),s%=mod;
        if(a2)s+=(a2-(las==3))*dfs(a1+1,a2-1,a3,a4,a5,2),s%=mod;
        if(a3)s+=(a3-(las==4))*dfs(a1,a2+1,a3-1,a4,a5,3),s%=mod;
        if(a4)s+=(a4-(las==5))*dfs(a1,a2,a3+1,a4-1,a5,4),s%=mod;
        if(a5)s+=a5*dfs(a1,a2,a3,a4+1,a5-1,5),s%=mod;
        return f[a1][a2][a3][a4][a5][las]=s;
    }
    int main()
    {
        scanf("%d",&k);int x;
        for(int i=1;i<=k;i++)scanf("%d",&x),a[x]++;
        printf("%lld
    ",dfs(a[1],a[2],a[3],a[4],a[5],0));
    }
  • 相关阅读:
    白帽子 攻防
    自定义WCF的配置文件
    .net快速创建PDF文档 by c#
    如何在面试中发现优秀程序员
    kafka-java客户端连接
    xshell 登陆堡垒机实现自动跳转
    良好的编程习惯
    Mycat-介绍
    scala-传名函数和传值函数
    springboot-31-springboot静态注入
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7688763.html
Copyright © 2011-2022 走看看