艰难取舍(seq.cpp/c/pas)
【题目描述】
由于hyf长得实在是太帅了,英俊潇洒,风流倜傥,人见人爱,花见花开,车见车载。有一群MM排队看hyf。每个 MM都有自己独特的风格,由于 hyf有着一颗包容的心,所以,什么风格的MM他都喜欢……
但是,hyf有一个特别的要求,他不希望总是看到风格得差不多的 MM,更加特别的是,如果两个MM风格完全一样,hyf不会有任何意见。
现在,hyf希望从去看他的 MM中,去掉一些MM,从而使得相邻2个 MM的风格值的差(绝对值)不为1。自然地,hyf希望去掉的MM越少越好。
【输入格式】
第一行一个整数N;
第 2~N+1行N 个整数,第i个为 ci。表示第i个MM的风格值。
【输出格式】
一个数,表示最少要去掉的 MM数。
【样例输入1】
6
4
2
2
1
1
1
【样例输出1】
2
【数据范围】
对于30%的数据,N≤20
对于70%的数据,N≤100,ci ≤ 2000
对于100%的数据,N≤1000 0 ≤ ci ≤ 2000
这道题可以用动态规划的算法来解决。
用数组F[i]来表示从第1个到第i个数最多可以留下几个。
那么显然F[i]可以由F[j](1<=j<=i-1)加1推得。即当前最优情况下与第i个数相邻的是第j个数,并且这里的j要满足i和j的差绝对值不为1。则F[i]=max{F[j]}+1,且|a[i]-a[j]|<>1。这个算法的时间复杂度为O(n^2)。
另外,可以发现a[j]与a[i]不能相邻的情况只有a[j]=a[i]+1和a[j]=a[i]-1。所以,不需穷举1到i-1,只需找出1到i-1中最大的3个F[j]即可,其中必须确保F[j]不彼此相等,这样满足条件的max{F[j]}必然是在这3个F[j]中,这样就可将算法的时间复杂度缩小到O(3N)。
这道题也可以用暴力枚举来实现,对于一个序列a1,a2,a3…an,可以]用一个数组b[a[i]]来记录到达a[i]的最大存在个数。通过枚举存在2个,3个,4个…n个人时的最大值来取得。
例:一开始只存在a1和a2,a3…an中的任意一个时的最大值放在b[a[i]]中,然后再搜索只存在3个人时a1,a2和a3,a4….an中的任意一个时的最大值,由于a1,a2两个人的最大值已存在b[a[2]]中了,所以只要寻找a2和a3,a4…an中任意一个的最大值即可,比较b[a[i]]是否大于b[a[2]]+1,并将结果放在b[a[i]]中。同理依次枚举至n个人为止。最后在b[1]…b[n]中找出最大值即可。
for i:=1 to n do//枚举每次存在从a[1]开始的i个人
for j:=i+1 to n do//更新前i个人和到第j个人之间的最大人数
if (abs(c[j]-c[i])<>1) and (s[i]+1>s[j]) then s[j]:=s[i]+1;
AC_code:
var j,i,n,maxs:longint; c,f:array[1..1001] of longint; function max(a,b:longint):longint; begin if a>b then exit(a); exit(b); end; begin assign(input,‘seq.in‘); assign(output,‘seq.out‘); reset(input);rewrite(output); readln(n); for i:=1 to n do readln(c[i]); for i:=1 to n do begin f[i]:=1; for j:=1 to i-1 do if abs(c[j]-c[i])<>1 then f[i]:=max(f[i],f[j]+1); end; maxs:=-0; for i:=1 to n do if f[i]>maxs then maxs:=f[i]; writeln(n-maxs); close(input);close(output); end.