[SCOI2008]着色方案

[SCOI2008]着色方案

https://ac.nowcoder.com/acm/problem/20265

题意:
给你n种染料,每种染料可以使用Ci次,同一种染料不能连续使用,求用完所有染料的方案数为多少种?

思路:
纯动态规划,我们用dp[a][b][c][d][e][last]描述一个还可以使用一次的染料为a种,还可以使用两次的染料为b种,.....,可以使用五次的染料为f种时上一次染色为使用还可以使用last次的染料。
我们可以分析状态是怎么来的得出状态转化方程,例如,dp[a][b][c][d][e][1]时,如果上上次不为2,则上一次则使用的为a+1种染料的其中一种,如果上上次为2,则说明上一次(a+1)种有一种不能使用,所以为a种中的其中一种。

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

#define inf 1000000007
#define eps 0.00000001
using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int maxn=100005;

inline int read()
{
    char c=getchar();
    int f=1, x=0;
    while(c>'9'||c<'0')
    {
        if(c=='-')
        {
            f=-1;
        }
        c=getchar();
    }
    while(c<='9'&&c>='0')
    {
        x=(x<<3)+(x<<1)+(c^48);
        c=getchar();
    }
    return f*x;
}

ll dp[20][20][20][20][20][10], a[10];

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        int c;
        scanf("%d",&c);
        a[c]++;
    }
    dp[a[1]][a[2]][a[3]][a[4]][a[5]][1]=1;
    for(int r=n;r>=0;r--)
    {
        for(int l=n;l>=0;l--)
        {
            for(int k=n;k>=0;k--)
            {
                for(int j=n;j>=0;j--)
                {
                    for(int i=n;i>=0;i--)
                    {
                        ll p=0;
                        for(int o=1;o<=5;o++)
                        {
                            if(o==2)
                            {
                                p=p+dp[i+1][j][k][l][r][o]*(i);
                                p=p%inf;
                            }
                            else
                            {
                                p=p+dp[i+1][j][k][l][r][o]*(i+1);
                                p=p%inf;
                            }
                        }
                        dp[i][j][k][l][r][1]=max(dp[i][j][k][l][r][1],p);
                        p=0;
                        for(int o=1;o<=5;o++)
                        {
                            if(i!=0)
                            {
                            if(o==3)
                            {
                                p=p+dp[i-1][j+1][k][l][r][o]*(j);
                                p=p%inf;
                            }
                            else
                            {
                                p=p+dp[i-1][j+1][k][l][r][o]*(j+1);
                                p=p%inf;
                            }
                            }
                        }
                        dp[i][j][k][l][r][2]=max(dp[i][j][k][l][r][2],p);
                        p=0;
                        for(int o=1;o<=5;o++)
                        {
                            if(j!=0)
                            {
                            if(o==4)
                            {
                                p=p+dp[i][j-1][k+1][l][r][o]*(k);
                                p=p%inf;
                            }
                            else
                            {
                                p=p+dp[i][j-1][k+1][l][r][o]*(k+1);
                                p=p%inf;
                            }
                            }
                        }
                        dp[i][j][k][l][r][3]=max(dp[i][j][k][l][r][3],p);
                        p=0;
                        for(int o=1;o<=5;o++)
                        {
                            if(k!=0)
                            {
                                if(o==5)
                                {
                                    p=p+dp[i][j][k-1][l+1][r][o]*l;
                                    p=p%inf;
                                }
                                else
                                {
                                    p=p+dp[i][j][k-1][l+1][r][o]*(l+1);
                                    p=p%inf;
                                }
                            }
                        }
                        dp[i][j][k][l][r][4]=max(dp[i][j][k][l][r][4],p);
                        p=0;
                        for(int o=1;o<=5;o++)
                        {
                            if(l!=0)
                            {
                                    p=p+dp[i][j][k][l-1][r+1][o]*(r+1);
                                    p=p%inf;
                            }
                        }
                        dp[i][j][k][l][r][5]=max(dp[i][j][k][l][r][5],p);
                        //printf("%d\n",dp[1][1][1][0][0][0]);
                    }
                }
            }
        }
    }
    cout << dp[0][0][0][0][0][1] << endl;
    return 0;
}
全部评论

相关推荐

点赞 评论 收藏
分享
来个厂收我吧:首先,市场侧求职我不是很懂。 但是,如果hr把这份简历给我,我会觉得求职人不适合做产品经理。 问题点: 1,简历的字体格式不统一,排版不尽如人意 2,重点不突出,建议参考star法则写个人经历 3,印尼官方货币名称为印度尼西亚卢比(IDR),且GMV690000印尼盾换算为305人民币,总成交额不高。 4,右上角的意向职位在发给其他公司时记得删除。 5,你所有的经历都是新媒体运营,但是你要投市场营销岗位,jd和简历不匹配,建议用AI+提示词,参照多个jd改一下经历内容。 修改建议: 1,统一字体(中文:思源黑体或微软雅黑,英文数字:time new romans),在word中通过表格进行排版(b站学) 2,校招个人经历权重:实习经历=创业经历(大创另算)>项目经历>实训经历>校园经历 3,请将项目经历时间顺序改为倒序,最新的放最上方。 4,求职方向不同,简历文字描述侧重点也需要不同。
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-25 13:59
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务