题目链接:https://vjudge.net/problem/UVALive-8328
题意: 给定一个算数式子 可能正确也可能不正确,问最少消去多少个式子可以让这个算数式子成立
思路: 1. 用队友提供的Dfs记忆化搜索 可以解决。找到从一个起点开始 可以链接最多的式子
2. 看到有大佬用的LIS(最长上升子序列的做法) 感觉也很有道理 也很简单易懂 这里放上
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 1000 + 10;
const int INF = 0x3f3f3f3f;
int n, ans;
int a[maxn], b[maxn], sum[maxn], dp[maxn], dig[maxn];
int main() {
// freopen("in.txt","r",stdin );
while(scanf("%d", &n) && n) {
ans = 0;
for(int i = 0; i < n; i++) scanf("%1d", &a[i]);
for(int i = 0; i < n; i++) scanf("%1d", &b[i]);
for(int i = 0; i < n; i++) scanf("%1d", &sum[i]);
memset(dig, 0, sizeof(dig));
memset(dp, 0, sizeof(dp));
for(int i = n - 1; i >= 0; i--) {
if(a[i] + b[i] == sum[i]) {
dig[i] = 0;
dp[i] = 1;
ans = max(ans, dp[i]);
}
if(a[i] + b[i] - 10 == sum[i]) {
dig[i] = 1;
dp[i] = 1;
}
for(int j = n - 1; j > i; j--) {
if(a[i] + b[i] + dig[j] == sum[i] && dp[i] < dp[j] + 1) {
dp[i] = dp[j] + 1;
dig[i] = 0;
ans = max(ans, dp[i]);
}
if(a[i] + b[i] + dig[j] - 10 == sum[i] && dp[i] < dp[j] + 1) {
dp[i] = dp[j] + 1;
dig[i] = 1; //存在进位的时候,无法确定这一位的去留
}
}
}
printf("%d\n", n - ans);
}
return 0;
}
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1000 + 10;
const int INF = 0x3f3f3f3f;
int dp[maxn], dight[maxn];
int n, ansQ, A[maxn], B[maxn], C[maxn];
int Dfs(int pos, int d) {
int &ans = dp[pos];
if(ans != -1) return ans;
int flag = 1;
ans = 1;
for(int j = pos - 1; j >= 1; j--) {
if((A[j] + B[j] + d) % 10 == C[j]) {
int cnt = Dfs(j, (A[j] + B[j] + d) / 10);
if(cnt != 0) {
flag = 0;
ans = max(ans, cnt + 1);
}
}
}
//这个代表了如果当前被认为是最高位的存在进位 肯定是不行的
if(flag && d) return ans = 0; //一定要更改ans的值 否则无法记忆化
return ans;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
while(scanf("%d", &n) && n) {
memset(dp, -1, sizeof(dp));
memset(dight, 0, sizeof(dight));
for(int i = 1; i <= n; i++) scanf("%1d", &A[i]);
for(int i = 1; i <= n; i++) scanf("%1d", &B[i]);
for(int i = 1; i <= n; i++) scanf("%1d", &C[i]);
for(int i = 1; i <= n; i++) {
int val = A[i] + B[i];
if(val >= 10 && val - 10 == C[i]) dight[i] = 1;
}
ansQ = 0;
for(int i = n ; i >= 1; i--) {
if((A[i] + B[i]) % 10 == C[i])
ansQ = max(ansQ, Dfs(i, dight[i]));
}
printf("%d\n", n - ansQ);
}
return 0;
}