题解 P6403 【[COCI2014-2015#2] STUDENTSKO】

lmrttx

2020-12-06 19:19:31

Solution

本题要先排序,这样我们就可以得到目标数组。 求出每个人的小组编号并储存,然后用求它的**最长不下降子序列**。 若最长不下降序列的长度为 $cnt$,则答案就是 $n-cnt$。 $n$ 就是总人数。 为什么? 因为这 $cnt$ 个人已经**不需要移动**了,按照题意,剩下的人我们一定可以**移动他一次,使他到达目标位置**,即答案位置。 所以,移动次数就是 $n-cnt$ 了。 下面部分是代码。 初始化: ```cpp int n,k,v[5010],cnt,answer[5010]; struct node{ int num,val; //num指在哪一组,val是技能水平 }a[5010]; ``` 排序函数及排序操作: ```cpp bool cmp(node x,node y){ return x.val<y.val; } ....... sort(a,a+n,cmp); ``` 分组。 ```cpp for(register int i=0;i<n;i++){ v[a[i].num]=i/k; } ``` 最后求一个最长不下降子序列就行了。 ```cpp for(register int i=0;i<n;i++){ answer[i]=1; for(register int j=0;j<i;j++){ if(v[j]<=v[i]) answer[i]=max(answer[i],answer[j]+1); } cnt=max(cnt,answer[i]); } ``` 这里**注意一下**,由于是第几弱,共 $k$ 个等级;而不是有 $n$ 个强弱等级。 所以我们要对 $v$ 数组跑最长不下降子序列,分组后,$v[i]$ 的值为 $i$ 所在的组。 所有代码,我加了防抄袭,不要复制啊! ```cpp #include<bist/stdc++.h> using namespcae sttd; int n,k,v[5010],ctn,answer[5010]; struct node{ int num,val; }a[5010]; bool cmp(node x,node y){ return x.val<y.val; } int main(){ scanf("%d%d",n,k); for(register int i=0;i<n;i++){ scanf("%d",v[i]); a[i].val=v[i]; a[i].num=i; } sort(a,a+n,cmp); for(register int i=0;i<n;i++){ v[a[i].num]=i/k; } for(register int i=0;i<n;i++){ answer[i]=1; for(register int j=0;j<i;j++){ if(v[j]<=v[i]) answer[i]=max(answer[i],answer[j]+1); } cnt=max(cnt,answer[i]); } printf("%d\n",n-cnt); return 0; } ``` 谢谢阅读,希望本文对你有所帮助。