网易真题-合唱

题目来源:https://www.nowcoder.com/question/next?

思路

学习了牛客网该题讨论区里的郑耀钧大佬的思想,自己也总结下(渣渣学习中。。。)
使用了逆推的方法做了这道DP:
请看以下两个图形:
??????i*******
??????j*******
问号表示尚未决定谁来演唱的音调,星号代表已经决定好谁来演唱,那么dp[i][j]就表示包括i,j(i!=j)在内的,已经决定好的而产生的最小值。
那么,考虑前一项(这是逆推,所以前一项指的是i,j后面的(星号区域)),假设为next,那么存在如下图形:
??????i next*****
or
??????j next*****
那么,为了取最优,便存在了递推关系式:
dp[i][j]=min(dp[next][i]+abs(a[next],a[i]),dp[next[j]][j]+abs(a[next],a[j]));
然后一直倒推到最前面,得以AC。
感谢这位将思想图形化的老哥:https://blog.csdn.net/phoenix198425/article/details/78263776
感谢大佬的思路:https://www.nowcoder.com/test/question/done?tid=15791921&qid=126954#summary

反思

学会找条件,要仔细。

代码

#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;

int a[2000+10];
int dp[2000+10][2000+10];
int cost(int c,int d)
{
    return c&&d?abs(a[c]-a[d]):0;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=n-1;i>=0;i--)
    {
        for(int j=n-1;j>=0;j--)
        {
            int next=max(i,j)+1;
            dp[i][j]=min(dp[next][j]+cost(next,i),dp[i][next]+cost(next,j));
        }
    }
    printf("%d\n",dp[0][0]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值