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.
The input contains multiple test cases.
Each test case include, first two integers n, P. (1
For each test case output the sequences according to the problem description. And at the end of each case follow a empty line.
3 5
1 3 2
3 6
1 3 2
4 100
1 2 3 2
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 2
Hint : You must make sure each subsequence in the subsequences is unique.
题意很简单就是在给定的序列中找到固定个数的递增的子序列,如果子序列的总个数少于要求的个数,那么就把所有的子序列输出即可,注意每组测试用例就为有一空行。
技巧一:重判,这里有两个重判,第一个重判是判断如果搜索的是子序列的第一个元素,那么判断从原始序列开始到当前位置是否已经出现过该元素,若出现过则之前肯定搜索过该元素,则放弃该元素的搜索。第二个重判,当搜索的不是子序列的第一个元素时,则判断子序列的前一个元素对应原始序列的位置,然后从该位置下一个元素开始到到当前搜索的位置之前判断该元素是否出现过,如果出现过,说明该子串出现过重复的,则放弃该元素。这里的两个重判需要好好地想想,很巧妙。
技巧二:剪枝,这里的一个剪枝技巧是做了一个标记位,假如我在搜索长度为3的子串时,发现没有一个符合的,那么就不可能存在长度为4的子串符合条件。如果没有这个剪枝就会超时,看来影响很大的
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#define N 1010
const int mm = 1000000007;
using namespace std;
int n, p;
int a[N], cnt, len, path[N];
bool flag;
bool ok(int s, int e)
{
for (int i = s; i < e; i++)
if (a[i] == a[e]) return false;
return true;
}
void dfs(int deep, int pos)
{
int i;
if (cnt >= p) return ;
if (deep == len)
{
flag = true;
cnt++;
for (i = 0; i < len-1; i++)
cout << a[path[i]] << ' ';
cout << a[path[i]] << endl;
return ;
}
for (i = pos; i < n; i++)
{
if (!deep || (deep && a[path[deep-1]] <= a[i]))
{
if (!deep && !ok(0, i)) continue ;
if (deep && !ok(path[deep-1]+1, i)) continue;
path[deep] = i;
dfs(deep+1, i+1);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int i, j;
while(cin >> n >> p)
{
for (i = 0; i < n; i++)
cin >> a[i];
cnt = 0;
for (i = 1; i <= n; i++)
{
flag = false;
len = i;
dfs(0, 0);
if (cnt >= p || !flag) break;
}
cout << endl;
}
return 0;
}
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 (<=100) 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 subsequence by lexicographical. For example initial sequence 1 3 2 the total legal subsequences is 5. According to order is {1}; {2}; {3}; {1,2}; {1,3}. If you also can not understand , please see the sample carefully.
The input contains multiple test cases.
Each test case include, first two integers n, P. (1
For each test case output the sequences according to the problem description. And at the end of each case follow a empty line.
3 5
1 3 2
3 6
1 3 2
4 100
1 2 3 2
1
2
3
1 2
1 3
1
2
3
1 2
1 3
1
2
3
1 2
1 3
2 2
2 3
1 2 2
1 2 3
Hint : You must make sure each subsequence in the subsequences is unique.
和前一题sequence one 属于一类题,都是dfs,首先排一次序,然后再检查时注意输入时的下标,生成的子串不能够出现下标非递增的,也就是首先子串时递增的,其次下标也是递增的,然后不能有重复的子串出现。
技巧:判重的技巧,这里我们可以一开始设置一个flag=false,第一次的时候该flag的为true,然后用一个pre保留当前位置的数,然后后面在搜相同len的序列时,如果当前的数与pre是一样的,说明先前已经搜过了,直接continue就行了,否则,pre就保留这个数,然后搜len+1的数。
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#define N 110
const int mm = 1000000007;
using namespace std;
struct aaa
{
int num, pos;
friend bool operator < (const aaa x, const aaa y)
{
if (x.num == y.num) return x.pos < y.pos;
return x.num < y.num;
}
}a[N];
int n, p;
int cnt, len, path[N];
bool dfs(int deep, int pos, int repos)
{
int i;
if (deep == len)
{
cnt++;
for (i = 0; i < len-1; i++)
cout << path[i] << ' ';
cout << path[i] << endl;
if (cnt == p)return true;
return false;
}
int pre;
bool flag = false;
for (i = pos; i <= n; i++)
{
if (a[i].pos > repos)
{
if (!flag)
{
flag = true;
pre = a[i].num;
}
else if (pre == a[i].num) continue;
pre = a[i].num;
path[deep] = a[i].num;
if (dfs(deep+1, i+1, a[i].pos)) return true;
}
}
return false;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int i, j;
while(cin >> n >> p)
{
for (i = 1; i <= n; i++)
{
cin >> a[i].num;
a[i].pos = i;
}
sort(a+1, 1+a+n);
cnt = 0;
for (i = 1; i < n; i++)
{
len = i;
if (dfs(0, 1, 0)) break;
}
cout << endl;
}
return 0;
}