DFS + 剪枝
代码:这道题目可以当做dfs来做(很多得26分的情况就是少判断了一种条件 例如 2 4 6 8 9 2 4 6,3个序列分别是:2 4 6 | 9 | 2 4 6 8当你判断到2 4 6觉得是第一个序列时,其实是2 4 6 8,但是它却是另一个序列,你并没有关心下一个是否匹配成功,就会陷入死循环),所以用dfs判断至最后一个元素时结束,当当前序列匹配成功时,对应总序列位置转移cnt+s[i].size()-1,再回溯,还需要用st数组来判断该序列是否被用过
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 100010;
int n, m, w[N], idx;
vector<int> g[N];
vector<int> res, now;
bool has_answer, st[N];
void dfs(int u) //u表示当前位于的位置
{
if(u >= n - 1)//因为下面的减一操作,这里也要减一
{
res = now;
has_answer = true;
return ;
}
if(has_answer) //剪枝,如果已经搜索到答案,后面就不用搜索了
return ;
for(int i = 1; i <= m; i ++ )
{
if(!st[i])
{
bool flag = true;
for(int j = 0; j < g[i].size(); j ++ ) //匹配所有高度
{
if(g[i][j] != w[u + j])
{
flag = false;
break;
}
}
if(flag)
{
st[i] = true;
now.push_back(i);
dfs(u + g[i].size() - 1);//之所以减一是因为两片碎纸会共用一个高度
st[i] = false;
now.pop_back();
}
}
}
}
int main()
{
cin >> n;
for(int i = 0; i < n; i ++ ) cin >> w[i];
cin >> m;
for(int i = 1; i <= m; i ++ )
{
int k; cin >> k;
while(k -- )
{
int x; cin >> x;
g[i].push_back(x);
}
}
dfs(0);//从第0个折线高度开始匹配
// cout << res.size() << endl;
for(int i = 0; i < res.size(); i ++ )
{
cout << res[i];
if(i != res.size() - 1) cout << " ";
}
return 0;
}