• bzoj-1079 着色方案(dp)


    Time Limit:10000MS     Memory Limit:165888KB   
    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

    题意:

    思路:

    f[a][b][c][d][e][x]表示能涂一个格子的油漆有a种,能涂两个格子的油漆有b种...x表示的是上一次涂的是能涂x个格子的油漆;

    f[a][b][c][d][e][x]=f[a-1][b][c][d][e]*(a-(x==2))+f[a+1][b-1][c][d][e]*(b-(x==3))+...+f[a][b][c][d+1][e-1]*(a-(x==6));

    这个方程表示,剩下a,b,c,d,e,上次的是x,

    假设这次要用可以涂k个格子的油漆,那么涂完这个格子,可以涂k个格子的油漆少了一种,可以涂k-1个格子的油漆多了一种;

    这就是为什么b-1的时候a+1,c-1的时候b+1的原因;

    还有就是相邻的格子的颜色不同,假设上一次用的是可以涂x个格子的油漆,那么上一次用完后的那种油漆就变成了一种可以涂x-1个格子的油漆了,那么这一次再选油漆的时候就不能再选可以涂x-1个格子的油漆的一种(这种上次一就用过了);所以对应的是*(a-(x==2))和*(b-(x==3))这些了;

    AC代码:

    //#include <bits/stdc++.h>
    #include <vector>
    #include <iostream>
    #include <queue>
    #include <cmath>
    #include <map>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    #define For(i,j,n) for(int i=j;i<=n;i++)
    #define mst(ss,b) memset(ss,b,sizeof(ss));
    
    typedef  long long LL;
    template<class T> void read(T&num) {
        char CH; bool F=false;
        for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
        for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
        F && (num=-num);
    }
    int stk[70], tp;
    template<class T> inline void print(T p) {
        if(!p) { puts("0"); return; }
        while(p) stk[++ tp] = p%10, p/=10;
        while(tp) putchar(stk[tp--] + '0');
        putchar('
    ');
    }
    
    const LL mod=1e9+7;
    const double PI=acos(-1.0);
    const LL inf=1e18;
    const int N=2e3+10;
    const int maxn=1005;
    const double eps=1e-10;
    
    int num[7];
    LL f[17][17][17][17][17][6];
    LL dp(int a,int b,int c,int d,int e,int x)
    {
        if(f[a][b][c][d][e][x]!=0)return f[a][b][c][d][e][x];
        LL ans=0;
        if(a)ans=(ans+(a-(x==2))*dp(a-1,b,c,d,e,1))%mod;
        if(b)ans=(ans+(b-(x==3))*dp(a+1,b-1,c,d,e,2))%mod;
        if(c)ans=(ans+(c-(x==4))*dp(a,b+1,c-1,d,e,3))%mod;
        if(d)ans=(ans+(d-(x==5))*dp(a,b,c+1,d-1,e,4))%mod;
        if(e)ans=(ans+e*dp(a,b,c,d+1,e-1,5))%mod;
        f[a][b][c][d][e][x]=ans;
        return ans;
    }
    int main()
    {
        int k,x;
        read(k);
        For(i,1,k)read(x),num[x]++;
        f[1][0][0][0][0][1]=1;
        cout<<dp(num[1],num[2],num[3],num[4],num[5],6)<<"
    ";
            return 0;
    }
  • 相关阅读:
    [转]MyBatis传入多个参数的问题
    【转】赶集网mysql开发36军规
    C#套接字和windowsAPI套接字
    java中的注解
    java中的枚举类型
    过去的汇编代码
    近日错误集锦
    java swing模仿随机频谱
    java泛型中的对象
    XML-RPC远程方法调用
  • 原文地址:https://www.cnblogs.com/zhangchengc919/p/5664503.html
Copyright © 2020-2023  润新知