题解|Eating Together

Eating Together

http://www.nowcoder.com/questionTerminal/b32e7c2ae14e41e5ae56e8e1771faad0

思路:dp

设两个二维数组f1与f2,它们的定义如下:

f1[i][j]:前i个数,最后一个数为j,使这i个数为升序的最小改变数

f2[i][j]:前i个数,最后一个数为j,使这i个数为降序的最小改变数

首先,f1与f2的边界条件为:

f1[1][j]=[d[i]=j]

f2[1][j]=[d[i]=j]

然后,经过简单的推理,容易得出dp方程:

f1[i][j]=min{f1[i-1][k]+[j=d[i]]} (1<=k<=j)

f1[i][j]=min{f1[i-1][k]+[j=d[i]]} (j<=k<=3)

最后,把f1[n][1~3]与f2[n][1~3]中的最小值取出来,就是答案。

以下为代码

#include<cstdio>
#include<cstring>
#define min(a,b) ((a)<(b)?(a):(b)) //手打min
int n,d[30010],ans1,ans2,f1[30010][4],f2[30010][4];
int main()
{
    scanf("%d",&n);
    memset(f1,0x3f,sizeof(f1)); //注意初始化
    memset(f2,0x3f,sizeof(f2));
    for(int i=1;i<=n;i++)
        scanf("%d",&d[i]);
    f1[1][1]=f1[1][2]=f1[1][3]=1;
    f1[1][d[1]]=0;
    for(int i=2;i<=n;i++)
        for(int j=1;j<=3;j++)
        {
            if(j!=d[i])
                for(int k=1;k<=j;k++)
                    f1[i][j]=min(f1[i-1][k]+1,f1[i][j]);
            else
                for(int k=1;k<=j;k++)
                    f1[i][j]=min(f1[i-1][k],f1[i][j]);
        }
    f2[1][1]=f2[1][2]=f2[1][3]=1; //复制上面的
    f2[1][d[1]]=0;
    for(int i=2;i<=n;i++)
        for(int j=1;j<=3;j++)
        {
            if(j!=d[i])
                for(int k=j;k<=3;k++) //注意是降序
                    f2[i][j]=min(f2[i-1][k]+1,f2[i][j]);
            else
                for(int k=j;k<=3;k++)
                    f2[i][j]=min(f2[i-1][k],f2[i][j]);
        }
    int ans=0x3f3f3f3f; //注意ans的初值要设为极大值
    for(int i=1;i<=3;i++) //统计答案
        ans=min(ans,min(f1[n][i],f2[n][i]));
    printf("%d\n",ans);
    return 0; //结束
}


全部评论

相关推荐

牛客92804383...:在他心里你已经是他的员工了
点赞 评论 收藏
分享
06-25 16:53
门头沟学院 Java
人力小鱼姐:简历可以直接用飞书模板 模拟面试可以试试ai,现在好多都还是免费阶段 像Sugar云面、多面鹅都不错,主要看面试后自己能不能复盘出有效信息
为了找工作你花了哪些钱?
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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