[CF792C] Divide by Three(dp,记录路径)

本文解析了一道Codeforces上的题目C,通过动态规划的方法解决如何最小化删除字符使得剩余字符串可被3整除的问题,并提供了详细的代码实现及注意事项。

题目链接:http://codeforces.com/contest/792/problem/C

题意:给个超长整数,问最少删掉几个数,使得这个数能被3整除。输出这个删掉字符后的字符串。

当然这个数各位加起来能被三整除,那么这个数就能被三整除。

很容易的dp,f(i,j)表示前i个字符各位和%3=j时,最少删掉几个字符。每层初始化为f(i,j) = min(f(i,j), f(i-1,j)+1)

转移就很简单,当前数为x,那么当前可以由f(i-1,(j-x+3)%3)转移过来。

 

有几个坑需要注意下:

1.初始化,要特别小心前导零存在的时候(s[0]-'0')%3==0的情况,因此判断一下是更新两个初始值还是一个就行。

2.再就是前导零处理起来特别麻烦,太麻烦了,参考了mengxiang巨的前导零排除方法,用每层初始化的值(删除)和当前字符个数判断,假如全删了,那说明当前状态之前都是0,后面就不转移了。

3.假如删了n个字符,要处理一下这个字符串是不是原本就有0,因为排除前导零的时候没有转移。

  1 /*
  2 ━━━━━┒ギリギリ♂ eye!
  3 ┓┏┓┏┓┃キリキリ♂ mind!
  4 ┛┗┛┗┛┃\○/
  5 ┓┏┓┏┓┃ /
  6 ┛┗┛┗┛┃ノ)
  7 ┓┏┓┏┓┃
  8 ┛┗┛┗┛┃
  9 ┓┏┓┏┓┃
 10 ┛┗┛┗┛┃
 11 ┓┏┓┏┓┃
 12 ┛┗┛┗┛┃
 13 ┓┏┓┏┓┃
 14 ┃┃┃┃┃┃
 15 ┻┻┻┻┻┻
 16 */
 17 #include <bits/stdc++.h>
 18 using namespace std;
 19 #define fr first
 20 #define sc second
 21 #define cl clear
 22 #define BUG puts("here!!!")
 23 #define W(a) while(a--)
 24 #define pb(a) push_back(a)
 25 #define Rint(a) scanf("%d", &a)
 26 #define Rll(a) scanf("%I64d", &a)
 27 #define Rs(a) scanf("%s", a)
 28 #define Cin(a) cin >> a
 29 #define FRead() freopen("in", "r", stdin)
 30 #define FWrite() freopen("out", "w", stdout)
 31 #define Rep(i, len) for(int i = 0; i < (len); i++)
 32 #define For(i, a, len) for(int i = (a); i < (len); i++)
 33 #define Cls(a) memset((a), 0, sizeof(a))
 34 #define Clr(a, x) memset((a), (x), sizeof(a))
 35 #define Full(a) memset((a), 0x7f7f7f, sizeof(a))
 36 #define lrt rt << 1
 37 #define rrt rt << 1 | 1
 38 #define pi 3.14159265359
 39 #define RT return
 40 #define lowbit(x) x & (-x)
 41 #define onenum(x) __builtin_popcount(x)
 42 typedef long long LL;
 43 typedef long double LD;
 44 typedef unsigned long long ULL;
 45 typedef pair<int, int> pii;
 46 typedef pair<string, int> psi;
 47 typedef pair<LL, LL> pll;
 48 typedef map<string, int> msi;
 49 typedef vector<int> vi;
 50 typedef vector<LL> vl;
 51 typedef vector<vl> vvl;
 52 typedef vector<bool> vb;
 53 
 54 const int maxn = 101010;
 55 const int inf = 0x7f7f7f7f;
 56 int n, f[maxn][3], path[maxn][3];
 57 char s[maxn];
 58 
 59 signed main() {
 60     // FRead();
 61     while(~Rs(s)) {
 62         n = strlen(s);
 63         if(n == 1) {
 64             if((s[0]-'0')%3==0) puts(s);
 65             else puts("-1");
 66             continue;
 67         }
 68         Clr(f, 0x7f); Clr(path, -1);
 69         if((s[0]-'0')%3==0) f[0][0] = 0;
 70         else f[0][0] = 1, f[0][(s[0]-'0')%3] = 0;
 71         For(i, 1, n) {
 72             int x = (s[i] - '0') % 3;
 73             Rep(j, 3) {    // delete
 74                 if(f[i][j] > f[i-1][j] + 1) {
 75                     f[i][j] = f[i-1][j] + 1;
 76                     path[i][j] = j;
 77                 }
 78             }
 79             Rep(j, 3) {
 80                 if(x == 0) {
 81                     if(s[i] == '0') {
 82                         if(f[i-1][j] == i) {
 83                             continue; // 0
 84                         }
 85                     }
 86                 }
 87                 int pre = (j - x + 3) % 3;
 88                 if(f[i][j] > f[i-1][pre]) {
 89                     f[i][j] = f[i-1][pre];
 90                     path[i][j] = pre;
 91                 }
 92             }
 93         }
 94         // cout << f[n-1][0] << endl;
 95         if(f[n-1][0] == n) {
 96             bool ok = 0;
 97             Rep(i, n) if(s[i] == '0') ok = 1;
 98             if(ok) puts("0");
 99             else puts("-1");
100             continue;
101         }
102         int i = n - 1, j = 0, pre;
103         string ret = "";
104         while(i) {
105             pre = path[i][j];
106             if(f[i-1][pre] == f[i][j]) ret += s[i];
107             j = pre; i--;
108         }
109         if((s[i] - '0') % 3 == pre) ret += s[i];
110         reverse(ret.begin(), ret.end());
111         cout << ret << endl;
112     }
113     RT 0;
114 }

 

转载于:https://www.cnblogs.com/kirai/p/7388853.html

<think>首先,用户的问题是关于PLECS仿真软件中出现“divide by zero”错误的解决方案。用户提到了一些引用,但指示说“上述引用仅供参考”,我应该主要参考用户上一次的问题和我的回答。回顾对话历史,用户之前的问题是关于PLECS的“divide by zero”错误,所以我需要针对这个提供解决方案。 关键点: - 用户希望了解“divide by zero”错误的原因和解决方法。 - 引用中提到的是PLECS Blockset的下载信息,但不是直接相关的。我应该忽略这个引用,因为它不是核心内容。 我的回答需要: - 结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。基于我对PLECS的了解,这是一个用于电力电子和控制系统仿真的软件。 - 使用中文回答。 - 遵循系统级指令:行内数学表达式用$...$,独立公式用$$...$$,LaTeX语法正确。 - 生成相关问题。 结构建议: 1. **解释原因**:简要说明为什么会出现“divide by zero”错误。 2. **提供解决方法**:列出常见解决方案,分步骤。 3. **生成相关问题**:在结尾添加相关问题。 原因:在仿真中,“divide by zero”通常发生在数学运算中,如除法、对数等,当分母为零时。在PLECS中,这可能源于模型设置、参数错误或数值问题。 解决方法: - 检查模型参数:确保所有输入参数不为零。 - 添加小偏移量:在除法前添加一个小常数,如$1e-6$。 - 使用条件语句:避免除以零的情况。 - 检查模型组件:如传感器、控制器等。 - 更新软件:确保使用最新版本,修复可能的bug。 - 仿真设置:调整步长或求解器。 基于引用,用户提到了PLECS 4.5.9,建议下载最新版本,所以我可以提及更新软件。 回答结构: - 开头:确认问题。 - 原因解释。 - 解决方法列表。 - 结尾:生成相关问题。 生成相关问题: - 例如:如何避免仿真中的数值错误?PLECS中常见错误有哪些?如何调试PLECS模型? 确保LaTeX: - 行内数学:如添加小偏移量,用$1e-6$。 - 独立公式:如果需要,但可能不必要,除非有数学公式。 最终回答: 1. 用中文。 2. 清晰步骤。 3. 添加相关问题。</think>### PLECS 中 "divide by zero" 错误的原因及解决方案 在 PLECS 仿真软件中出现 "divide by zero" 错误,通常是由于模型中的数学运算(如除法或对数)在分母为零时触发的数值问题。这可能导致仿真中断,影响分析结果。常见原因包括: - **参数设置错误**:模型中的某些参数(如电阻值、电容值或初始条件)被意外设置为零。 - **数值不稳定**:仿真过程中,变量值趋近于零,导致除法运算失败。 - **模型组件问题**:如传感器、控制器或自定义模块中的逻辑错误。 - **求解器设置不当**:仿真步长过大或求解器类型不匹配,加剧数值误差。 以下我将逐步介绍解决方案,帮助您诊断和修复此错误。建议基于真实可靠的工程实践,并结合 PLECS 官方文档[^1]。 #### 步骤 1: 检查模型参数和初始条件 - **原因分析**:模型中如果有除法运算(例如$1/x$),当$x$接近或等于零时,会触发错误。 - **解决方法**: - 仔细审查所有参数设置,确保分母变量(如电阻、电感或时间常数)不为零。例如,在 PLECS 模型编辑器中,检查所有输入框。 - 为潜在为零的变量添加一个小偏移量(如$1e-6$),以避免除以零。例如,将除法表达式修改为$1/(x + \epsilon)$,其中$\epsilon$是一个很小的常数(例如$10^{-6}$)。 - 使用条件语句(如 if-else 逻辑)在分母接近零时跳过运算。在 PLECS 中,可以通过自定义脚本或使用 "Switch" 模块实现。 #### 步骤 2: 审查模型组件和连接 - **原因分析**:错误可能源于特定组件(如传感器、反馈回路或自定义函数),导致数值不稳定。 - **解决方法**: - 隔离可疑组件:逐步禁用部分模型(例如断开反馈回路),运行仿真以定位错误源。 - 检查自定义代码:如果使用 MATLAB Function 或 S-Function 模块,确保代码中包含防除以零的逻辑。例如: ```matlab % 示例:在自定义函数中添加保护 function y = safe_divide(u1, u2) if abs(u2) < 1e-6 y = 0; % 或设置默认值 else y = u1 / u2; end end ``` - 验证连接:确保所有信号线正确连接,避免未定义变量。 #### 步骤 3: 调整仿真设置 - **原因分析**:PLECS 的求解器(如 ode45 或 ode15s)可能因步长过大而放大数值误差。 - **解决方法**: - 减小仿真步长:在 "Simulation > Configuration Parameters" 中,将 "Max step size" 设置为更小值(例如从自动调整为$0.001$秒)。 - 更换求解器:尝试更稳健的求解器,如 "ode23tb"(适用于 stiff 系统)。 - 启用零检测:在求解器选项中勾选 "Zero-crossing detection",帮助避免分母过零点。 #### 步骤 4: 更新软件和检查 bug - **原因分析**:旧版本 PLECS 可能存在已知 bug,导致除以零错误。 - **解决方法**: - 下载最新版本:如引用所述,PLECS 4.5.9 包含了额外错误修复[^1]。建议从 [PLECS 官方下载页面](https://www.plexim.com/download/blockset) 更新。 - 如果必须使用旧版(如 4.5.6),确保应用所有补丁,并参考官方论坛或支持文档。 #### 步骤 5: 高级调试技巧 - **使用日志工具**:在 PLECS 中启用 "Debug mode",查看实时变量值,定位错误发生时的具体位置。 - **简化模型**:创建一个最小可复现模型(仅包含关键组件),测试是否仍出现错误
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值