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 的方案数 $\times 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[i-1][0]*2 + dp[i-1][1]
\)
\(
dp[i][1] = dp[i-1][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[i-1][0]
\)
\(
dp[i][1] = dp[i-1][1]*2 + dp[i-1][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\) 个字符串不反转,令 \(s_i\) 有序的最小代价
dp[i][1] 表示第 \(i\) 个字符串反转,令 \(s_i\) 有序的最小代价
初始化:
\( dp[1][0] = 0; \ dp[1][1] = c_1 \)
转移方程:
如果 \(s_{i-1}\) 不转 \(\leqslant s_i\) 不转:
\( dp[i][0] = \min(dp[i][0], dp[i-1][0]) \)
如果 \(s_{i-1}\) 转 \(\leqslant s_i\) 不转:
\( dp[i][0] = \min(dp[i][0], dp[i-1][1]) \)
如果 \(s_{i-1}\) 不转 \(\leqslant s_i\) 转:
\( dp[i][1] = \min(dp[i][1], dp[i-1][0] + c_i) \)
如果 \(s_{i-1}\) 转 \(\leqslant s_i\) 转:
\( dp[i][1] = \min(dp[i][1], dp[i-1][1] + c_i) \)
最后的答案是 \(\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;
}
浙公网安备 33010602011771号