G - Railroad UVALive - 4888
输入:
n m
n个数
m个数
n+m个数
输出:
若第一行和第二行合并能形成第三行 possible, 否则not possible。(每次只能取两列数其中的第一个)
方法一:DP
#include<cstdio>
#include<cstring>
#define N 1010
int a[N], b[N], c[2*N], dp[N][N];
///dp[i][j] 表示用第一行的前i个和第二行前j个能不能形成第三行前i+j个
int main()
{
int i, n, m, j;
while(scanf("%d %d", &n, &m)&&n&&m)
{
for(i = 1; i <= n; i++)
scanf("%d", &a[i]);
for(i = 1; i <= m; i++)
scanf("%d", &b[i]);
for(i = 1; i <= n+m; i++)
scanf("%d", &c[i]);
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for(i = 0; i <= n; i++)
for(j = 0; j <= m; j++)
{
if (i > 0 && a[i] == c[i+j] && dp[i-1][j] == 1)
dp[i][j] = 1;
if (j > 0 && b[j] == c[i+j] && dp[i][j-1] == 1)
dp[i][j] = 1;
}
if (dp[n][m] == 1)
printf("possible\n");
else
printf("not possible\n");
}
return 0;
}
方法二:递归遍历
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define N 1010
int n, m;
int a[N], b[N], c[2*N], vis[N][N];
int flag;
void Find(int x, int y)
{
if (flag)
return ;///一旦找到就返回
if (vis[x][y])
return ;
if (x == n && y == m)
{
flag = 1;
return ;
}
if (x < n && a[x+1] == c[x+y+1])
Find(x+1, y);
if (y < m && b[y+1] == c[x+y+1])
Find(x, y+1);
vis[x][y] = 1;
}
int main()
{
int i;
while(scanf("%d %d", &n, &m)&&n&&m)
{
flag = 0;
memset(vis, 0, sizeof(vis));
for(i = 1; i <= n; i++)
scanf("%d", &a[i]);
for(i = 1; i <= m; i++)
scanf("%d", &b[i]);
for(i = 1; i <= m+n; i++)
scanf("%d", &c[i]);
Find(0, 0);
if (flag)
printf("possible\n");
else
printf("not possible\n");
}
return 0;
}