1. 程式人生 > >洛谷-【動態規劃】- 大朋友的數字

洛谷-【動態規劃】- 大朋友的數字

在NOIP2013的賽場上,常神牛華麗麗的手殘了,小朋友的數字一題只得了10分。於是,他要惡搞一下這道題。

題目描述

有一批大朋友(年齡15歲以上),他們每人手上拿著一個數字,當然這個數字只有1位,也就是0到9之間。每個大朋友的分數為在他之前的最長不下降子序列中所有數之和。(這個序列必須以它作為結尾!)如有多個最長不下降子序列,那麼取編號字典序最小的。現在告訴你有n個大朋友,以及他們各自的數字,請你求出他們每個人的分數。

輸入輸出格式

輸入格式:

輸入檔案為bignum.in。

第一行,1個數n。

第二行,n個數,分別表示每個人的數字。

輸出格式:

輸出檔案為bignum.out。

一行,n個數,分別表示每個人的分數。

輸入輸出樣例

輸入樣例#1: 複製

【輸入輸出樣例1】
5
1 2 5 3 4
【輸入輸出樣例2】
5
1 7 5 9 6

輸出樣例#1: 複製

【輸入輸出樣例1】
1 3 8 6 10
【輸入輸出樣例2】
1 8 6 17 12

說明

【樣例解釋1】

五個人分數分別為(1),(1+2),(1+2+5),(1+2+3),(1+2+3+4).

【樣例解釋2】

五個人分數分別為(1),(1+7),(1+5),(1+7+9){還有一個(1,5,9)},(1+5+6)。

【資料規模】

對於50%的資料,1≤n≤500;

對於80%的資料,1≤n≤1000;

對於100%的資料,1≤n≤10,000。

題解:基於最長上升子序列改造,只不過這裡加了要求字典序最小,就是選擇某個位置之前的一個數是它最接近這個位置的數,就像輸入樣例2,1,7,5,9,6在9這個位置是選擇1,7,9這個序列而不選1,5,9這個序列,題意明白了,接下用來程式碼實現就行了。

import java.util.*;
/*
 *大朋友的數字
 */
public class test{
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        int[] a=new int[n+1];
        for(int i=1;i<=n;i++) {
        	a[i]=in.nextInt();
        }
        int[] dp=new int[n+1];
        int[] c=new int[n+1];
        for(int i=1;i<=n;i++) {
        	dp[i]=1;
        	for(int j=1;j<i;j++) {
        		if(a[i]>=a[j]) {
        			if(dp[i]<dp[j]+1) {
        				dp[i]=dp[j]+1;
        				c[i]=c[j];//c[i]等於離它最近的一個數c[j]因為要求字典序最小 
        			}
        		}
        	}
        	c[i]+=a[i];//自身也是序列的一個數
        }
        for(int i=1;i<=n;i++) {
        	System.out.print(c[i]+" ");
        }
    }
}