BZOJ1806: [Ioi2007]Miners 矿工配餐

Posted Star_Feel

tags:

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

【传送门:BZOJ1806


简要题意:

  有两个矿洞,有三种食物,给出n个食物的配送顺序,每个食物可以给任意一个矿洞,每个食物送到一个矿洞的收益是这个矿洞最近三次(包括送的那次)食物的种类数

  请你经过合理的分配食物使得收益最大


题解:

  水题DP

  设f[i][t1][t2][t3][t4]为当前已经送了i个食物,且最近两次给第一个矿洞送了第t1和t2种食物(t1比t2更早送),给第二个矿洞送了第t3和t4种食物(t3比t4更早送)能得到的最大收益

  假如t1,t2,t3,t4为0,表示当前没有送那么多的餐

  转移想想就会了

  然后这题卡空间。。

  没关系,滚动数组一下就好了


参考代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
char st[110000];
int f[2][4][4][4][4];
int a[110000];
int main()
{
    int n;
    scanf("%d",&n);
    scanf("%s",st+1);
    for(int i=1;i<=n;i++)
    {
        if(st[i]==M) a[i]=1;
        if(st[i]==F) a[i]=2;
        if(st[i]==B) a[i]=3;
    }
    memset(f,-1,sizeof(f));
    f[0][0][0][0][0]=0;
    int now=0,last=1;
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        now^=1;last^=1;
        for(int t1=0;t1<=3;t1++)
        {
            for(int t2=0;t2<=3;t2++)
            {
                int d1=0;
                if(t1!=0&&t2==0)
                {
                    d1=1;if(t1!=a[i]) d1=2;
                }
                else if(t1==0&&t2!=0)
                {
                    d1=1;if(t2!=a[i]) d1=2;
                }
                else if(t1!=0&&t2!=0)
                {
                    if(t1==t2)
                    {
                        d1=1;if(t1!=a[i]) d1=2;
                    }
                    else
                    {
                        d1=2;if(t1!=a[i]&&t2!=a[i]) d1=3;
                    }
                }
                else d1=1;
                for(int t3=0;t3<=3;t3++)
                {
                    for(int t4=0;t4<=3;t4++)
                    {
                        int d2=0;
                        if(t3!=0&&t4==0)
                        {
                            d2=1;if(t4!=a[i]) d2=2;
                        }
                        else if(t3==0&&t4!=0)
                        {
                            d2=1;if(t4!=a[i]) d2=2;
                        }
                        else if(t3!=0&&t4!=0)
                        {
                            if(t3==t4)
                            {
                                d2=1;if(t3!=a[i]) d2=2;
                            }
                            else
                            {
                                d2=2;if(t3!=a[i]&&t4!=a[i]) d2=3;
                            }
                        }
                        else d2=1;
                        if(f[last][t1][t2][t3][t4]!=-1)
                        {
                            f[now][t2][a[i]][t3][t4]=max(f[now][t2][a[i]][t3][t4],f[last][t1][t2][t3][t4]+d1);
                            f[now][t1][t2][t4][a[i]]=max(f[now][t1][t2][t4][a[i]],f[last][t1][t2][t3][t4]+d2);
                            ans=max(ans,max(f[now][t2][a[i]][t3][t4],f[now][t1][t2][t4][a[i]]));
                        }
                    }
                }
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

 

以上是关于BZOJ1806: [Ioi2007]Miners 矿工配餐的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1806: [Ioi2007]Miners 矿工配餐

bzoj1806[Ioi2007]Miners 矿工配餐 dp

1806: [Ioi2007]Miners 矿工配餐

bzoj1806

[IOI2007]Miners

矿工配餐_IOI2007Miners