[SCOI2008]着色方案

这题也是看了别人题解也才会做的。
题解:
本题用的记忆优化搜索,题目说了给的颜色可以恰好图够所有木块。
题目给了能涂几块木块的颜色一共有几种。因为我们不可以连续图,所以我们把他分开来涂色。
用dp[a][b][c][d][e][last]
表示能涂a​表示的是能涂1个木块颜色还有a个,前一个涂得颜色是last个颜色时方案总数。
表示能涂b​表示的是能涂2个木块颜色还有b个,前一个涂得颜色是last个颜色时方案总数。

既然不可以连续图,所以我们把能连续图的颜色拆分开来使用。
比如说我要用一下子可以涂四个木块的颜色来涂,因为不可以连续,所以我们只让这个颜色图一个木块,那么这个颜色还可以图三个木块,所以我们让可以图三个木块的颜色+1.
如下:

if(d) res=(res+(d-(last==5))*dfs(a,b,c+1,d-1,e,4))%mod;

但是(last==4)表示的是什么意思呢?其实不难理解,如果你要用能涂四个木块的颜色涂,你需要特判一下,上一个木块涂得颜色是不是由5转化为4的,如果不去初这一个,那么相同颜色又挨在一起了。

/*Keep on going Never give up*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <math.h>
#include <string>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
const int maxn = 3e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1e9+7;
using namespace std;
int t[20];
ll dp[16][16][16][16][16][6];

ll dfs(int a,int b,int c,int d,int e,int last){
    if(dp[a][b][c][d][e][last]!=-1) return dp[a][b][c][d][e][last];
    if(a+b+c+d+e==0) return 1;
    ll res=0;
    if(a) res=(res+(a-(last==2))*dfs(a-1,b,c,d,e,1))%mod;
    if(b) res=(res+(b-(last==3))*dfs(a+1,b-1,c,d,e,2))%mod;
    if(c) res=(res+(c-(last==4))*dfs(a,b+1,c-1,d,e,3))%mod;
    if(d) res=(res+(d-(last==5))*dfs(a,b,c+1,d-1,e,4))%mod;
    if(e) res=(res+e*dfs(a,b,c,d+1,e-1,5));
    dp[a][b][c][d][e][last]=res%mod;
    return dp[a][b][c][d][e][last];
}

int main() {
    int k;
    cin>>k;
    memset(dp,-1,sizeof(dp));
    for(int i=0;i<k;i++){
        int x;
        cin>>x;
        t[x]++;
    }
    ll ans=dfs(t[1],t[2],t[3],t[4],t[5],0);
    cout<<ans<<endl;
    return 0;
}






猜你喜欢

转载自blog.csdn.net/xxxxxiao123/article/details/107506624
今日推荐