序列DP(输出有要求)

DP

Time Limit:10000MS     Memory Limit:165888KB     64bit IO Format:%lld & %llu
Submit Status

Description

  对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm)且( ax1 < ax
2 < … < axm)。那么就称P为S的一个上升序列。如果有多个P满足条件,那么我们想求字典序最小的那个。任务给
出S序列,给出若干询问。对于第i个询问,求出长度为Li的上升序列,如有多个,求出字典序最小的那个(即首先
x1最小,如果不唯一,再看x2最小……),如果不存在长度为Li的上升序列,则打印Impossible.

Input

  第一行一个N,表示序列一共有N个元素第二行N个数,为a1,a2,…,an 第三行一个M,表示询问次数。下面接M
行每行一个数L,表示要询问长度为L的上升序列。N<=10000,M<=1000

Output

  对于每个询问,如果对应的序列存在,则输出,否则打印Impossible.

Sample Input

6
3 4 1 2 3 6
3
6
4
5

Sample Output

Impossible
1 2 3 6
Impossible


//序列DP题,DP是真的要思维。。。一定要想到最佳的DP方法,一般DP方法能做出来还是TLE了
这里 DP[i] 代表序列以第 i 个元素为开头的上升序列的可达的最大长度,然后,做过序列DP的应该都会做了
从后向前转移状态 DP[i] = max ( DP[i] , DP[j] + 1 ) num[i] < num [j] && i < j

 1 #include <stdio.h>
 2 
 3 #define INF 1000000000
 4 int num[10005];//数据
 5 int dp[10005];//记录到这最大上升长度
 6 int ans[10005];//存储答案的
 7 int n,m;
 8 
 9 void Init()
10 {
11     scanf("%d",&n);
12     int i,j;
13     for (i=1;i<=n;i++)
14         scanf("%d",&num[i]);
15     for (i=n;i>=1;i--)
16     {
17         dp[i]=1;
18         for (j=i+1;j<=n;j++)
19         {
20             if (num[j]>num[i]&&dp[j]+1>dp[i])
21             {
22                 dp[i]=dp[j]+1;
23             }
24         }
25     }
26 }
27 
28 int main()
29 {
30     Init();
31     scanf("%d",&m);
32     while (m--)
33     {
34         int i,j,l,ok=0;
35         scanf("%d",&l);
36 
37         int pos;
38         for (i=1;i<=n;i++)
39         {
40             if (ok==0&&dp[i]>=l)
41             {
42                 int tmp=1;
43                 ans[1]=num[i];
44                 if (tmp==l)
45                 {
46                     ok=1;
47                     break;
48                 }
49                 int pre=i;
50                 for (j=i+1;j<=n;j++)
51                 {
52                     if (num[j]>num[pre]&&dp[j]>=l-tmp)
53                     {
54                         ans[++tmp]=num[j];
55                         pre=j;
56                         if (tmp==l)
57                         {
58                             ok=1;
59                             break;
60                         }
61                     }
62                 }
63             }
64         }
65         if (ok==0)
66             printf("Impossible\n");
67         else
68         {
69             for (i=1;i<l;i++)
70                 printf("%d ",ans[i]);
71             printf("%d\n",ans[l]);
72         }
73 
74     }
75     return 0;
76 }
View Code

 



posted @ 2016-11-09 18:47  happy_codes  阅读(316)  评论(0编辑  收藏  举报