首页 > 代码库 > 序列DP(输出有要求)

序列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

63 4 1 2 3 63645

Sample Output

Impossible1 2 3 6Impossible


//序列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         else68         {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

 



序列DP(输出有要求)