申请添加题解
查看原帖
申请添加题解
1419923
ZYStream楼主2024/10/27 09:12

这道题最初的思路是用数值大的打数值小的,而且这一打不能使数值大的那个浪费,先对r数组进行排序(规定从第一项开始)

sort(r+1,r+1+n);

然后r数组就成了一个不严谨的单调递增序列,只需要将r[i]攻击r[i-1]项就行,如果r[i]=r[i-1],那么r[i]和r[i-1]两个元素无法死亡。 我们用dp[i]表示在排过序的r数组中,从第一项到第i项时,最多会死掉多少个元素,易得到状态转移方程式为

dp[i] = r[dp[i-1]+1]==r[i]?dp[i-1]:dp[i-1]+1.

如果条件表达式看不懂的话,可以看这个

if(r[i]==r[dp[i-1]+1]) dp[i]=dp[i-1];
else dp[i]=dp[i-1]+1;

那么解释一下这个方程式,dp[i]既然可以表示最多死亡个数,那么死亡的元素一定是数组中比较小的,截至到r[i],死亡的元素是r[1~dp[i]],如果r[i]=r[dp[i-1]+1],就说明两个即将对战的元素相等,那么我们就知道这两个元素谁都打不死谁,所以dp[i]=dp[i-1]。否则就说明r[i]可以击败r[dp[i-1]+1],所以dp[i]=dp[i-1]+1 当i为1时,答案一定是1,所以i从2开始遍历 最后输出答案n-dp[n]即可
AC代码:

#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int r[100005];
int dp[100005];
int main(){
    //freopen("duel.in","r",stdin);
    //freopen("duel.out","w",stdout);
    scanf("%lld",&n);
    for (int i=1;i<=n;i++){
        scanf("%lld",&r[i]);
    }
    sort(r+1,r+n+1);
    for (int i=2;i<=n;i++) dp[i] = r[dp[i-1]+1]==r[i]?dp[i-1]:dp[i-1]+1;
    printf("%lld",n-dp[n]);
    return 0;
}

再说一些其他的,这道题的答案和他所给的数据中重复元素出现的次数有关,当所给的数据都不重复时,答案就是1,当所有数据都一样时,答案就是n,这个是考完试发现的,具体就不多说了

2024/10/27 09:12
加载中...