zoukankan      html  css  js  c++  java
  • [BZOJ1079/Luogu2476][SCOI2008]着色方案

    题目链接:

    BZOJ1079

    Luogu2476

    记忆化搜索+(DP)

    首先看到数据范围就知道状态是个(15^5)的级别而不是(5^{15})了。

    那么显然设(f_{a,b,c,d,e})表示还有(a)种颜色剩(1)个,(b)种剩两个,(cdots)(e)种剩(5)个时的方案数。

    但是如何判断两个颜色不能相邻呢?

    如果记录上一次的颜色,那么这次判断也需要颜色,则状态爆炸。

    发现无论上次是什么颜色,只需要判断是否相同即可。

    那么就记录上一次选的颜色现在还剩几个,在转移时如果相同那么方案数就要少一种选择。

    综上,我们得到了如下的转移式:

    [f_{a,b,c,d,e,PreRem}+=f_{a-1,b,c,d,e,0}*(a-[PreRem==1]) (a>0) ]

    其中(PreRem)代表上一次选的颜色现在剩几个。

    如果还有(a)个颜色(1),那么可以更新答案,(PreRem)变为(0),此时有(a)种颜色可选,故答案(*a)

    同时如果(PreRem==1),那么说明这(a)种颜色中有一种与之前重复,不能选,只剩(a-1)种颜色可选,答案(*(a-1))

    对于其他(4)项转移方程也同理(别忘记在低项加上刚用掉的颜色)。

    时间复杂度 (O(k^c))

    #include <cstdio>
    #include <cstring>
    
    int k,c[10];
    int f[16][16][16][16][16][6];
    const int Mod=1000000007;
    
    int DP(int a,int b,int c,int d,int e,int PreRem)
    {
    	if(!a&&!b&&!c&&!d&&!e)return 1;
    	int &Ans=f[a][b][c][d][e][PreRem];
    	if(~Ans)return Ans;
    	Ans=0;
    	if(a)(Ans+=DP(a-1,b,c,d,e,0)*1LL*(PreRem==1?a-1:a)%Mod)%=Mod;
    	if(b)(Ans+=DP(a+1,b-1,c,d,e,1)*1LL*(PreRem==2?b-1:b)%Mod)%=Mod;
    	if(c)(Ans+=DP(a,b+1,c-1,d,e,2)*1LL*(PreRem==3?c-1:c)%Mod)%=Mod;
    	if(d)(Ans+=DP(a,b,c+1,d-1,e,3)*1LL*(PreRem==4?d-1:d)%Mod)%=Mod;
    	if(e)(Ans+=DP(a,b,c,d+1,e-1,4)*1LL*(PreRem==5?e-1:e)%Mod)%=Mod;
    	return Ans;
    }
    
    int main()
    {
    	scanf("%d",&k),memset(f,-1,sizeof f);
    	for(int cs;k--;)scanf("%d",&cs),++c[cs];
    	printf("%d
    ",DP(c[1],c[2],c[3],c[4],c[5],0));
    	return 0;
    }
    
  • 相关阅读:
    461. Hamming Distance
    342. Power of Four
    326. Power of Three
    368. Largest Divisible Subset java solutions
    95. Unique Binary Search Trees II java solutions
    303. Range Sum Query
    160. Intersection of Two Linked Lists java solutions
    88. Merge Sorted Array java solutions
    67. Add Binary java solutions
    14. Longest Common Prefix java solutions
  • 原文地址:https://www.cnblogs.com/LanrTabe/p/10178395.html
Copyright © 2011-2022 走看看