T1:复合逻辑表达式

本题难度中等,线性 dp 问题。根据最后一个运算递推:如果是 AND,需要两边都是 true;如果是 OR,只需任意一个是 true

S[i] = 'AND'
y[i-1]=T 且 x[i]=T: y[i] = T
y[i-1]=T 且 x[i]=F: y[i] = F
y[i-1]=F 且 x[i]=T: y[i] = F
y[i-1]=F 且 x[i]=F: y[i] = F

y[i]=T 的方案数等于 y[i-1]=T 的方案数
y[i]=F 的方案数等于 y[i-1]=F 的方案数 ×2 + y[i-1]=T 的方案数等于 y[i-1]=T 的方案数

dp[i][0] 表示 y[i]=F 的方案数,dp[i][1] 表示 y[i]=T 的方案数
转移方程:

s[i]='AND' 时:
dp[i][0]=dp[i1][0]2+dp[i1][1]
dp[i][1]=dp[i1][1]

s[i]='OR' 时:

y[i-1]=F 或 x[i]=F: y[i] = F
y[i-1]=T 或 x[i]=F: y[i] = T
y[i-1]=F 或 x[i]=T: y[i] = T
y[i-1]=T 或 x[i]=T: y[i] = T

dp[i][0]=dp[i1][0]
dp[i][1]=dp[i1][1]2+dp[i1][0]

答案是 dp[n][1]

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
ll dp[65][2];
int main() {
int n;
cin >> n;
vector<string> s(n);
rep(i, n) cin >> s[i];
dp[0][0] = dp[0][1] = 1;
rep(i, n) {
if (s[i] == "AND") {
dp[i+1][0] = dp[i][0]*2 + dp[i][1];
dp[i+1][1] = dp[i][1];
}
else {
dp[i+1][0] = dp[i][0];
dp[i+1][1] = dp[i][1]*2 + dp[i][0];
}
}
cout << dp[n][1] << '\n';
return 0;
}

T2:反转字符串排序

本题难度中等,也是线性dp问题,需要加 1 维记录结尾单词有没有反转。

状态表示:

dp[i][0] 表示第 i 个字符串不反转,令 si 有序的最小代价
dp[i][1] 表示第 i 个字符串反转,令 si 有序的最小代价

初始化:

dp[1][0]=0; dp[1][1]=c1

转移方程:

如果 si1 不转 si 不转:

dp[i][0]=min(dp[i][0],dp[i1][0])

如果 si1si 不转:

dp[i][0]=min(dp[i][0],dp[i1][1])

如果 si1 不转 si 转:

dp[i][1]=min(dp[i][1],dp[i1][0]+ci)

如果 si1si 转:

dp[i][1]=min(dp[i][1],dp[i1][1]+ci)

最后的答案是 min(dp[n][0],dp[n][1])

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
inline void chmin(ll& x, ll y) { if (x > y) x = y; }
int main() {
int n;
cin >> n;
vector<int> c(n);
rep(i, n) cin >> c[i];
vector<string> s(n);
rep(i, n) cin >> s[i];
vector<string> r = s;
rep(i, n) {
reverse(r[i].begin(), r[i].end());
}
const ll INF = 1e18;
vector<vector<ll>> dp(n+1, vector<ll>(2, INF));
dp[0][0] = 0;
dp[0][1] = c[0];
for (int i = 1; i < n; ++i) {
if (s[i-1] <= s[i]) chmin(dp[i][0], dp[i-1][0]);
if (r[i-1] <= s[i]) chmin(dp[i][0], dp[i-1][1]);
if (s[i-1] <= r[i]) chmin(dp[i][1], dp[i-1][0]+c[i]);
if (r[i-1] <= r[i]) chmin(dp[i][1], dp[i-1][1]+c[i]);
}
ll ans = min(dp[n-1][0], dp[n-1][1]);
if (ans == INF) ans = -1;
cout << ans << '\n';
return 0;
}