1045
题意:给定两个序列a和b,要求从b中找出一个最长的子序列符合各个元素的顺序是a序列的子序列。
题解:容易想到这是一个动态规划,维护一个数组dp[i][j],代表对于a序列的前i个元素组成的子串,可以从b序列的前j个子串中找到的最长子序列。转移方程的一部分和公共最长子序列相同,如下:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
if (a[i] == b[j])
{
dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);
}
另外,由于b序列的子序列中,多个相同的连续元素可以对应a序列中的单个元素,所以,还需要维护一个p[i][j]数组,其意思为a序列的前i个元素组成的子串,和b序列中,颜色为j的最长匹配。其转移方式如下:
dp[i][j] = max(dp[i][j], p[i][b[j]] + 1);
if (a[i] == b[j])
p[i][b[j]] = max(p[i][b[j]], dp[i][j]);
代码:
#include <bits/stdc++.h>
using namespace std;
const int Maxn = 205;
const int MaxL = 10004;
int dp[Maxn][MaxL];
int p[Maxn][Maxn];
int N, M, L;
int a[Maxn];
int b[MaxL];
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> N;
cin >> M;
for (int i = 1; i <= M; i++)
{
cin >> a[i];
}
cin >> L;
for (int i = 1; i <= L; i++)
{
cin >> b[i];
}
for (int i = 1; i <= M; i++)
{
for (int j = 1; j <= L; j++)
{
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
if (a[i] == b[j])
{
dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);
}
dp[i][j] = max(dp[i][j], p[i][b[j]] + 1);
if (a[i] == b[j])
p[i][b[j]] = max(p[i][b[j]], dp[i][j]);
}
}
cout << dp[M][L];
// cin >> M;
}
1048
题意:给定一个数字和一个序列,从序列中找出两个元素,使得他们的和为这个给定的数字。
题解:容易想到用数组维护序列中每个元素的数量,从1到给定的数字进行遍历,找到即退出循环。
代码:
#include <bits/stdc++.h>
using namespace std;
const int Maxn = 1e5 + 10;
int cnt[Maxn];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
cnt[x]++;
}
int p1 = -1, p2 = -1;
for (int i = 0; i <= m && m - i >= i; i++)
{
if (cnt[i] && cnt[m - i] && m - i != i)
{
p1 = i, p2 = m - i;
break;
}
if (m - i == i && cnt[i] >= 2 && p1 == -1)
{
p1 = p2 = i;
}
}
if (p1 == -1)
{
cout << "No Solution";
}
else
{
cout << p1 << " " << p2 << "\n";
}
// cin >> n;
}
迭代子模式
迭代子模式的结构
迭代子模式有两种实现方式,分别是白箱聚集与外禀迭代子和黑箱聚集于内禀迭代子。
白箱聚集与外禀迭代子
如果一个聚集的接口提供了可以用来修改聚集元素的方法,这个接口就是所谓的宽接口。
如果聚集对象为所有对象提供同一个接口,也就是宽接口的话,当然会满足迭代子模式对迭代子对象的要求。但是,这样会破坏对聚集对象的封装。这种提供宽接口的聚集叫做白箱聚集。聚集对象向外界提供同样的宽接口
由于聚集自己实现迭代逻辑,并向外部提供适当的接口,使得迭代子可以从外部控制聚集元素的迭代过程。这样一来迭代子所控制的仅仅是一个游标而已,这种迭代子叫做游标迭代子(Cursor Iterator)。由于迭代子是在聚集结构之外的,因此这样的迭代子又叫做外禀迭代子(Extrinsic Iterator)。
现在看一看白箱聚集与外禀迭代子的实现。一个白箱聚集向外界提供访问自己内部元素的接口(称作遍历方法或者Traversing Method),从而使外禀迭代子可以通过聚集的遍历方法实现迭代功能。
因为迭代的逻辑是由聚集对象本身提供的,所以这样的外禀迭代子角色往往仅仅保持迭代的游标位置。
一个典型的由白箱聚集与外禀迭代子组成的系统如下图所示,在这个实现中具体迭代子角色是一个外部类,而具体聚集角色向外界提供遍历聚集元素的接口。
迭代子模式涉及到以下几个角色:
● 抽象迭代子(Iterator)角色:此抽象角色定义出遍历元素所需的接口。
● 具体迭代子(ConcreteIterator)角色:此角色实现了Iterator接口,并保持迭代过程中的游标位置。
● 聚集(Aggregate)角色:此抽象角色给出创建迭代子(Iterator)对象的接口。
● 具体聚集(ConcreteAggregate)角色:实现了创建迭代子(Iterator)对象的接口,返回一个合适的具体迭代子实例。
● 客户端(Client)角色:持有对聚集及其迭代子对象的引用,调用迭代子对象的迭代接口,也有可能通过迭代子操作聚集元素的增加和删除。