Sequence one
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 526 Accepted Submission(s): 198
Problem Description
Search is important in the acm algorithm. When you want to solve a problem by using the search method, try to cut is very important.
Now give you a number sequence, include n (<=1000) integers, each integer not bigger than 2^31, you want to find the first P subsequences that is not decrease (if total subsequence W is smaller than P, than just give the first W subsequences). The order of subsequences is that: first order the length of the subsequence. Second order the sequence of each integer’s position in the initial sequence. For example initial sequence 1 3 2 the total legal subsequences is 5. According to order is {1}; {3}; {2}; {1,3}; {1,2}. {1,3} is first than {1,2} because the sequence of each integer’s position in the initial sequence are {1,2} and {1,3}. {1,2} is smaller than {1,3}. If you also can not understand , please see the sample carefully.
Now give you a number sequence, include n (<=1000) integers, each integer not bigger than 2^31, you want to find the first P subsequences that is not decrease (if total subsequence W is smaller than P, than just give the first W subsequences). The order of subsequences is that: first order the length of the subsequence. Second order the sequence of each integer’s position in the initial sequence. For example initial sequence 1 3 2 the total legal subsequences is 5. According to order is {1}; {3}; {2}; {1,3}; {1,2}. {1,3} is first than {1,2} because the sequence of each integer’s position in the initial sequence are {1,2} and {1,3}. {1,2} is smaller than {1,3}. If you also can not understand , please see the sample carefully.
Input
The input contains multiple test cases.
Each test case include, first two integers n, P. (1<n<=1000, 1<p<=10000).
Each test case include, first two integers n, P. (1<n<=1000, 1<p<=10000).
Output
For each test case output the sequences according to the problem description. And at the end of each case follow a empty line.
Sample Input
3 5 1 3 2 3 6 1 3 2 4 100 1 2 3 2
Sample Output
1 3 2 1 3 1 2 1 3 2 1 3 1 2 1 2 3 1 2 1 3 2 3 2 2 1 2 3 1 2 2HintHint : You must make sure each subsequence in the subsequences is unique.
题解:这一题题目意思有点难懂,大意是要你找到前P个子串,每个子串都需要是不下降子串(数字不递减),而子串间的大小又是由子串长度和子串中每个数字在原来串中的位置决定的。很明显这一题要剪枝(题目都说了When you want to solve a problem by using the search method, try to cut is very important......)1000的长度裸搜肯定过不了,所以想到如下剪枝:
1、所选的数不能大于前一个数。
2、前缀相同时,同一位置,同一个数仅仅搜一次。
3、在搜位置为i时,如果后面剩下数的个数小于我需要的个数,直接返回。
4、如果长度为i的序列搜不到解,那么比他长的序列也肯定搜不到(感觉这个是最重要的)
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n,p,a[1005],sta[1005],h,ans;
bool vis[1005],f;
void finish()
{
for (int i=0;i<h-1;i++) printf("%d ",sta[i]);
printf("%d\n",sta[h-1]);
ans++;
}
bool check(int last,int d,int x,int p)
{
return x>=last && !vis[p];
}
void dfs(int last,int lastp,int d,int l)
{
if (n-lastp<l-d) return;
bool flag[1005];
memset(flag,0,sizeof(flag));
if (d==l)
{
finish(); f=1;
return ;
}
for (int i=lastp+1;i<=n;i++) if (check(last,d,a[i],i) && !flag[a[i]])
{
sta[h++]=a[i]; flag[a[i]]=1; vis[i]=1;
dfs(a[i],i,d+1,l);
if (ans==p) return;
sta[--h]=0; vis[i]=0;
}
}
int main()
{
while (scanf("%d%d",&n,&p)!=EOF)
{
ans=0;
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int l=1;l<=n-1;l++)
{
f=0;
memset(vis,0,sizeof(vis));
memset(sta,0,sizeof(sta)); h=0;
dfs(0,0,0,l);
if (!f) break;
if (ans==p) break;
}
printf("\n");
}
return 0;
}