一道简单DP【然而对于我来说还是难,看了很多题解才明白】
题目大意:输入字符串a,b,c 要求判断c是否有a,b中的个字符保持原有顺序组合而成。
算法思想:
DP
用dp[i][j]表示a的前0~i-1共i个字符和b的前0~j-1共j个字符是否构成c[i+j-1].
状态转换方程:
if(i>=1&&c[i+j-1]==a[i-1])
dp[i][j]=dp[i][j]||dp[i-1][j](如果dp[i-1][j]是真的话,通过c[i+j-1]==a[i-1]就知dp[i][j]也为真,否则为假)
if(j>=1&&c[i+j-1]==b[j-1])
dp[i][j]=dp[i][j]||dp[i][j-1]
注意:下标问题 dp[1][1]表示有a的前1个字符(即a[0])和b的前一个字符(即b[0]),能否组成c[1+1-1](即c[0]+c[1])
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
int t,m=0;
cin >> t;
while (t--)
{
char s1[205];
char s2[205];
char s3[405];
int dp[205][205];
cin >> s1;
cin >> s2;
cin >> s3;
memset(dp, 0, sizeof(dp));
int len1 = strlen(s1);
int len2 = strlen(s2);
if (s1[0] == s3[0])
{
dp[1][0] = 1;
}
if (s2[0] == s3[0])
{
dp[0][1] = 1;
}
for (int i = 0; i <= len1; i++)
{
for (int j = 0; j <= len2; j++)
{
if (i >= 1 &&dp[i-1][j]&&(s3[i + j - 1] == s1[i - 1]))
{
dp[i][j] = 1;
}
if (j >= 1 &&dp[i][j-1]&& (s3[i + j - 1] == s2[j - 1]))
{
dp[i][j] = 1;
}
}
}
cout << "Data set "<<++m<<": ";
if (dp[len1][len2])
{
cout << "yes" << endl;
}
else
{
cout << "no" << endl;
}
}
return 0;
}