动态规划一般分四种模型:
1.从左到右,例如背包问题。
2.范围上尝试的,L-R。
3.str1行,str2列,玩二维表,或者对应表。
4.随意试,用分支限界的方法来规定限制条件。
题目:给定三个字符 str1,str2,aim包含且仅包含来自str1,str2的所有字符。
str1="ab",str2="12".那么"AB12","A1B2","A12B","1A2B","1AB2"都是str1 str2的交错组成。
此为经典的动态规划模式。
三个信息点:1.dp意义:dp[i][j] 代表aim[0,i+j-1] 能否被str1[0..i-1] str2[0..j-1]组成。
2. aim 长度 m+n
3.返回最右下角的值
四个步骤:1.dp[0][0] 赋值 aim空时true
2.第一列赋值 dp[0...col][0] aim[0..i-1]?=str1[0..i-1]
3.第一行赋值 dp[0][0...row] aim[0..j-1]?=str2[0...j-1]
4.dp[i][j]
4.1上位置+以前 (str1[i-1]==aim[i+j-1])+(str1[0..i-2],str2[0...j-1],aim[0...i+j-2])
4.2左位置+以前 (str2[j-1]==aim[i+j-1])+(str1[0...i-1],str2[0...j-2],aim[0...i+j-2])
上代码:
bool isCross(string str1, string str2, string aim)
{
int i_max = str1.size();
int j_max = str2.size();
if (aim.size() != (i_max + j_max))
{
cout << "aim.size() != (i_max + j_max)" << endl;
return false;
}
vector<vector<bool> > dp(j_max + 1);// 行 row str2
for (int i = 0; i < i_max + 1; i++)
{
dp[i].resize(i_max + 1);//列 col str1
}
//1.dp[0][0]=true;
dp[0][0] = true;
//2.col列 str1 i j 都是从1开始的
for (int i = 1; i <= i_max; i++)
{
if (str1[i-1]==aim[i-1])
{
dp[i][0] = true;
}
else
{
dp[i][0] = false;
}
}
//3.row 行 str2
for (int j = 1; j <= j_max; j++)
{
if (str2[j-1]==aim[j-1])
{
dp[0][j] = true;
}
else
{
dp[0][j] = false;
}
}
//4 dp[i][j]
//4.1 左dp[i][j-1]
//4.2 上dp[i-1][j]
for (int i = 1; i <=i_max; i++)
{
for (int j = 1; j <= j_max; j++)
{
bool topbefore = dp[i - 1][j];
bool leftbefore = dp[i][j - 1];
bool top = (str1[i - 1] == aim[i + j - 1] ? true : false);
bool left = (str2[j - 1] == aim[i + j - 1]?true : false);
if ((topbefore==true && top==true)||(leftbefore == true && left == true))
{
dp[i][j] = true;
}
}
}
return dp[i_max][j_max];
}
void strArrCross_main()
{
cout<<"***strArrCross_main**********"<<endl;
string str1 = "AB";
string str2 = "12";
string aim1 = "AB12";
string aim2 = "A1B2";
string aim3 = "A12B";
string aim4 = "1AB2";
cout << isCross(str1, str2, aim1) << endl;
cout << isCross(str1, str2, aim2) << endl;
cout << isCross(str1, str2, aim3) << endl;
cout << isCross(str1, str2, aim4) << endl;
}