做这题的时候我第一感觉是直接dfs的dp,用dp[i][j]表示第一个数组处理到第i位数字,第二个数组处理到第j个数字,能否组合出第三个数组的前cur个数字。
转移的话,就是试试第i为能否匹配第cur个了,如果可以就直接搜,不可以就看看第j位,都不可以就false
这样转移起来我觉得很明朗,实在想不到怎么用数组来dp。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> #include <bitset> int n1, n2; const int maxn = 1000 + 20; int a[maxn], b[maxn], c[maxn * 2]; int vis[maxn][maxn], DFN, dp[maxn][maxn]; bool dfs(int cur, int pos1, int pos2) { if (cur == n1 + n2 + 1) return true; if (vis[pos1][pos2] == DFN) return dp[pos1][pos2]; vis[pos1][pos2] = DFN; if (a[pos1] == c[cur]) { if (dfs(cur + 1, pos1 + 1, pos2)) { dp[pos1][pos2] = true; return true; } } if (b[pos2] == c[cur]) { if (dfs(cur + 1, pos1, pos2 + 1)) { dp[pos1][pos2] = true; return true; } } dp[pos1][pos2] = false; return false; } void work() { ++DFN; for (int i = 1; i <= n1; ++i) scanf("%d", &a[i]); for (int i = 1; i <= n2; ++i) scanf("%d", &b[i]); a[n1 + 1] = b[n2 + 1] = inf; for (int i = 1; i <= n1 + n2; ++i) scanf("%d", &c[i]); if (dfs(1, 1, 1)) { printf("possible "); } else printf("not possible "); } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif while (scanf("%d%d", &n1, &n2) != EOF && (n1 + n2)) work(); return 0; }