bzoj1079

Posted mikuknight

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1079相关的知识,希望对你有一定的参考价值。

来自 ljh的结题报告.
解题报告:

  这道题好神啊,合并操作的确很具有代表性。

  如果考虑如何求方案数,不妨DP统计,因为直接枚举与转移复杂度太大。我们选择把剩余可涂次数相等的分为一类,考虑因为只要剩余可涂次数相等,那么其实这些颜色并没有什么区别,因为我们涂颜色的时候只需要考虑涂的这种颜色剩余次数即可,并不需要考虑具体是什么颜色(先不考虑相邻颜色不能相等的限制)。

  那么令f[a1][a2][a3][a4][a5]表示剩余可涂一次的颜色种类数为a1,涂二次颜色种类数为a2...这样的情况的方案数。

  显然如果我们当前这次选的是剩余次数为x次的颜色,那么剩余次数为x次的颜色有多少种,就有多少种情况可以转移过来,只需要乘以数量就可以了。

  但是我们还没考虑相邻不能相等的情况,那么我们必须要少算一次,比如说如果上次填的是颜色剩余次数为2的,意味着颜色中剩余次数为1的多了一个,那么这一次并不能再选这种颜色,这次可以选填1的就要少1

//It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#ifdef WIN32   
#define OT "%I64d"
#else
#define OT "%lld"
#endif
using namespace std;
typedef long long LL;
const int MOD = 1000000007;
int n,num[10001];
LL f[16][16][16][16][16][6];//按每种颜色的剩余次数分类,剩余次数相同的分在一类

inline int getint()
{
       int w=0,q=0;
       char c=getchar();
       while((c<'0' || c>'9') && c!='-') c=getchar();
       if (c=='-')  q=1, c=getchar();
       while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
       return q ? -w : w;
}

inline LL dp(int a1,int a2,int a3,int a4,int a5,int last){    
    if( (a1 | a2 | a3 | a4 | a5 ) == 0)  return f[a1][a2][a3][a4][a5][last]=1;
    if(f[a1][a2][a3][a4][a5][last]) return f[a1][a2][a3][a4][a5][last];
    LL now=0;
    //考虑枚举这次选哪种剩余次数的颜色,一共有多少个剩余这种次数的个数就有多少种选择
    if(a1) now+=(a1-(last==2))*dp(a1-1,a2,a3,a4,a5,1),now%=MOD;//如果上次填的是颜色剩余次数为2的,意味着颜色中剩余次数为1的多了一个,那么这一次并不能再选这种颜色,这次可以选填1的就要少1。
    if(a2) now+=(a2-(last==3))*dp(a1+1,a2-1,a3,a4,a5,2),now%=MOD;
    if(a3) now+=(a3-(last==4))*dp(a1,a2+1,a3-1,a4,a5,3),now%=MOD;
    if(a4) now+=(a4-(last==5))*dp(a1,a2,a3+1,a4-1,a5,4),now%=MOD;
    if(a5) now+=a5*dp(a1,a2,a3,a4+1,a5-1,5),now%=MOD;//显然不需要考虑6的情况
    f[a1][a2][a3][a4][a5][last]=now;
    return now;
}

inline void work(){
    n=getint(); int x; for(int i=1;i<=n;i++) x=getint(),num[x]++;
    printf("%lld",dp(num[1],num[2],num[3],num[4],num[5],0));
}

int main()
{
  work();
  return 0;
}

以上是关于bzoj1079的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1079: [SCOI2008]着色方案

bzoj 1079: [SCOI2008]着色方案

[BZOJ1079][SCOI2008]着色方案

BZOJ 1079: [SCOI2008]着色方案

bzoj1079: [SCOI2008]着色方案(dp)

[BZOJ1079][SCOI2008]着色方案 dp