863872555 863872555
一个逐步走向成熟的高中生
关注数: 8 粉丝数: 7 发帖数: 1,233 关注贴吧数: 13
【题解】 tyvj p1208 ☆最长不下降子序列2 描述 Description 设有整数序列b1,b2,b3,…,bm,若存在i1<i2<i3<…<in,且bi1<bi2<bi3<…<bin,则称 b1,b2,b3,…,bm中有长度为n的不下降序列bi1,bi2,bi3,…,bin。求序列b1,b2,b3,…,bm中所有长度(n)最大不下降子序列 输入格式 Input Format 第一行为m,表示m个数 第二行m个数 输出格式 Output Format 第一行输出最大长度n 第二行输出长度为n的序列个数Total 样例输入 Sample Input 3 1 2 2 样例输出 Sample Output 2 1 时间限制 Time Limitation 各个测试点1s 注释 Hint 具有相同元素的序列,我们称之为重复序列,这里我们不统计重复序列,也即是说,重复的是算一次 DP经典题方法一: 对原序列按a从小到大(当ai=aj时按F从小到大)排序,增设Order(i)记录新序列中的I个数在原序列中的位置。可见,当求Total(i)时,当F(j)=F(j+1) , a(j)=a(j+1)且Order(j+1)<Order(i)时,便不累加Total(j)。这样就避免了重复。 var i,j,k,ans,n,len,t:longint; order,f,a,tot:array[0..2000] of longint; function max(a,b:longint):longint; begin if a>b then exit(a); exit(b); end; begin fillchar(f,sizeof(f),0); fillchar(tot,sizeof(tot),0); readln(n); for i:=1 to n do read(a[i]); readln; f[1]:=1; for i:=2 to n do begin f[i]:=1; for j:=1 to i-1 do if a[i]>a[j] then f[i]:=max(f[i],f[j]+1); end; len:=0; for i:=1 to n do len:=max(len,f[i]); ans:=0; writeln(len); for i:=1 to n do order[i]:=i; for i:=1 to n-1 do for j:=i+1 to n do if (a[i]>a[j])or((a[i]=a[j])and(f[i]>f[j])) then begin t:=order[i]; order[i]:=order[j]; order[j]:=t; t:=a[i]; a[i]:=a[j]; a[j]:=t; t:=f[i]; f[i]:=f[j]; f[j]:=t; end; for i:=1 to n do begin if f[i]=1 then tot[i]:=1 else for j:=1 to i-1 do if (a[j]<a[i])and(f[j]=f[i]-1)and(order[j]<order[i]) then if (f[j]<>f[j+1])or(a[j]<>a[j+1])or(order[j+1]>=order[i]) then inc(tot[i],tot[j]); if (f[i]=len)and(a[i]<>a[i+1]) then inc(ans,tot[i]); end; writeln(ans); end. 方法2:例如:(1,2,2,4) 对第2个2构成的方案数,都可由第3个2构成,所以第2个2的方案数不累加。 var i,j,n,maxlen,l:longint; a,len,ans:array[0..5000] of longint; begin readln(n); for i:=1 to n do read(a[i]); readln; for i:=1 to n do len[i]:=1; for i:=1 to n-1 do for j:=i+1 to n do if (a[j]>a[i])and(len[j]<len[i]+1) then len[j]:=len[i]+1; maxlen:=1; for i:=1 to n do if maxlen<len[i] then maxlen:=len[i]; a[n+1]:=maxlongint; len[n+1]:=maxlen+1; for i:=1 to n do if len[i]=1 then ans[i]:=1 else ans[i]:=0; ans[n+1]:=0; for l:=1 to maxlen do for i:=1 to n do if len[i]=l then begin j:=i+1; while (j<=n+1)and(a[j]<>a[i]) do begin if (a[j]>a[i])and(len[j]=len[i]+1) then inc(ans[j],ans[i]); inc(j); end; end; writeln(maxlen); writeln(ans[n+1]); end.
1 下一页