钢骨 https://www.e-learn.cn/tag/ganggu-0 zh-hans UVA10723 电子人的基因 Cyborg Genes https://www.e-learn.cn/topic/3243691 <span>UVA10723 电子人的基因 Cyborg Genes</span> <span><span lang="" about="/user/97" typeof="schema:Person" property="schema:name" datatype="">两盒软妹~`</span></span> <span>2020-01-17 00:05:31</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"> <h1><span style="text-decoration: underline; color: #ff9900;"><em>题意翻译</em></span></h1> <h2><span style="color: #800080; font-size: 18pt;">【题目描述】</span></h2> <p><span style="font-size: 14pt; font-family: 仿宋;">输入两个<span class="katex"><span class="katex-mathml"><span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord mathit">A~<span class="katex"><span class="katex-mathml"><span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord mathit">Z组成的字符串(长度均不超过<span class="katex"><span class="katex-mathml"><span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord">3<span class="mord">0),找一个最短的串,使得输入的两个串均是它的子序列(不一定连续出现)。你的程序还应统计长度最短的串的个数。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <p><span class="katex" style="font-size: 14pt; font-family: 仿宋;"><span class="katex-mathml">e.g.:ABAAXGF<span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord mathit"><span class="mord"><span class="mord mathit"><span class="mord"><span class="mrel"><span class="mord mathit"><span class="mord mathit"><span class="mord mathit"><span class="mord mathit"><span class="mord mathit"><span class="mord mathit"><span class="mord mathit">和<span class="katex"><span class="katex-mathml">AABXFGA<span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord mathit"><span class="mord mathit"><span class="mord mathit"><span class="mord mathit"><span class="mord mathit"><span class="mord mathit"><span class="mord mathit">的最优解之一为<span class="katex"><span class="katex-mathml"><span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord mathit">A<span class="mord mathit">A<span class="mord mathit">B<span class="mord mathit">A<span class="mord mathit">A<span class="mord mathit">X<span class="mord mathit">G<span class="mord mathit">F<span class="mord mathit">G<span class="mord mathit">A,一共有<span class="katex"><span class="katex-mathml">9<span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord">个解。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <h2><span style="color: #800080; font-size: 18pt;">【输入格式】</span></h2> <p><span style="font-size: 14pt; font-family: 仿宋;">有多组数据。第一行一个整数<span class="katex"><span class="katex-mathml"><span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord mathit">T表示数据组数。接下来的<span class="katex"><span class="katex-mathml">2<span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord"><span class="mord mathit">T行,每行一个字符串,含义如题所示。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <h2><span style="color: #800080; font-size: 18pt;">【输出格式】</span></h2> <p><span style="font-size: 14pt; font-family: 仿宋;">共<span class="katex"><span class="katex-mathml">T<span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord mathit">行。第<span class="katex"><span class="katex-mathml">i<span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord mathit">行格式为</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <p><span style="font-size: 14pt; font-family: 仿宋;"><code>Case #i: x y</code></span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">其中<span class="katex"><span class="katex-mathml"><span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord mathit">x为最短串的长度,<span class="katex"><span class="katex-mathml"><span class="katex-html"><span class="strut"><span class="strut bottom"><span class="base"><span class="mord mathit">y为最优解的个数。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <h1><span style="text-decoration: underline; color: #ff9900;"><em>题目描述</em></span></h1> <h1><span style="font-size: 18pt; font-family: 'Microsoft YaHei';"><a href="https://uva.onlinejudge.org/external/107/p10723.pdf" rel="nofollow">PDF</a></span></h1> <p> </p> <h1><span style="text-decoration: underline; font-family: 仿宋;"><em><span style="color: #ff9900; text-decoration: underline;">解析:</span></em></span></h1> <p><span style="font-size: 14pt; font-family: 仿宋;"><span style="text-decoration: line-through;">作为一名生物渣渣,蒟蒻再次感到了多方面综合发展的必要性。。。</span><span style="text-decoration-line: line-through;">。</span></span></p> <p><span style="text-decoration-line: line-through; font-size: 14pt; font-family: 仿宋;">最近老做最短路,今天我们就来做一道很水(nan)的动态规划~</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">下面我们进入正题,这个题的本质是求:<strong>最短公共超序列的长度和个数;</strong></span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">所谓的最短公共超序列,其实可以这样通俗地理解:找到一个最短的串,让给定的两个串都是这个新串的子序列。</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">这个题和最短公共超序列板子的唯一的不同就是需要统计超序列的个数。</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">于是我们可以先跑一边最短公共超序列。</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">设dp[i][j]表示a串前i个字符,b串前j个字符所构成的最短公共超序列长度。</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">在真正进行dp之前,首先初始化dp数组。</span></p> <p> </p> <div> <pre>for(int i=1;i&lt;=100;i++)dp[i][0]=dp[0][i]=i;</pre> </div> <p><span style="font-size: 14pt; font-family: 仿宋;">然后我们来想状态转移方程。</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">当a[i]==b[j]时,最短公共超序列最后一位是确定的,它的长度一定是这两个串之前的超序列长度+1,其中的1表示这个字符本身。</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">当他们不同时,去选择之前状态中最短的一个,实际上是对应超序列中最后一位a[i]还是b[j]。</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">于是完整的状态转移方程不难写出:</span></p> <p> </p> <pre>1 if(a[i-1]==b[j-1])dp[i][j]=dp[i-1][j-1]+1;//a[i],b[j]减1是因为循环变量是从1循环到&lt;=len; 2 else dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1);</pre> <p> </p> <p><span style="font-size: 14pt; font-family: 仿宋;">跑完了最短公共超序列,我们就可以开始统计它的个数。</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">设f[i][j]表示a串前i个字符,b串前j个字符所构成的最短公共超序列个数。</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">同样,在正式统计之前,先进行初始化。</span></p> <p>  <span class="cnblogs_code"><span style="color: #008080;">1</span> <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> i=<span style="color: #800080;">0</span>;i&lt;=<span style="color: #800080;">100</span>;i++)f[i][<span style="color: #800080;">0</span>]=f[<span style="color: #800080;">0</span>][i]=<span style="color: #800080;">1</span>;</span> </p> <p><span style="font-size: 14pt; font-family: 仿宋;">然后我们开始统计。</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">当a[i]==b[j]的时候,序列的末尾是确定的,只有一种可能性。所以f[i][j]=f[i-1][j-1];</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">当a[i]!=b[j]的时候,哪个超序列更短取哪个。</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">最后就是当他们的超序列不同但是长度相同时,两个都可以取,加起来就好。</span></p> <p><span style="font-size: 14pt; font-family: 仿宋;">完整的统计过程:</span></p> <p> </p> <pre>1 if(a[i-1]==b[j-1])f[i][j]=f[i-1][j-1]; 2 else if(dp[i-1][j]&lt;dp[i][j-1])f[i][j]=f[i-1][j]; 3 else if(dp[i-1][j]&gt;dp[i][j-1])f[i][j]=f[i][j-1]; 4 else f[i][j]=f[i-1][j]+f[i][j-1];</pre> <p> </p> <h1><span style="text-decoration: underline;"><span style="text-decoration-line: underline; font-family: 仿宋; color: #ff9900;"><em>最后上AC代码:</em></span></span></h1> <p> </p> <img id="code_img_closed_522fdf9f-8b72-4996-8760-42d9bcc4ad36" class="code_img_closed b-lazy" alt="" data-src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" data-original="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><img id="code_img_opened_522fdf9f-8b72-4996-8760-42d9bcc4ad36" class="code_img_opened b-lazy" style="display: none;" onclick="cnblogs_code_hide('522fdf9f-8b72-4996-8760-42d9bcc4ad36',event)" alt="" data-src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" data-original="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" /><div id="cnblogs_code_open_522fdf9f-8b72-4996-8760-42d9bcc4ad36" class="cnblogs_code_hide"> <pre> 1 #include&lt;iostream&gt; 2 #include&lt;cstring&gt; 3 #include&lt;cstdio&gt; 4 #include&lt;string&gt; 5 using namespace std; 6 string a,b; 7 int dp[105][105],f[105][105],t; 8 int main() 9 { 10 cin&gt;&gt;t; 11 getchar(); 12 for(int k=1;k&lt;=t;k++) 13 { 14 memset(dp,0,sizeof(dp)); 15 memset(f,0,sizeof(f)); 16 getline(cin,a); 17 getline(cin,b); 18 int len1=a.size(),len2=b.size(); 19 for(int i=1;i&lt;=100;i++)dp[i][0]=dp[0][i]=i; 20 for(int i=1;i&lt;=len1;i++) 21 { 22 for(int j=1;j&lt;=len2;j++) 23 { 24 if(a[i-1]==b[j-1])dp[i][j]=dp[i-1][j-1]+1; 25 else dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1); 26 } 27 } 28 for(int i=0;i&lt;=100;i++)f[i][0]=f[0][i]=1; 29 for(int i=1;i&lt;=len1;i++) 30 { 31 for(int j=1;j&lt;=len2;j++) 32 { 33 if(a[i-1]==b[j-1])f[i][j]=f[i-1][j-1]; 34 else if(dp[i-1][j]&lt;dp[i][j-1])f[i][j]=f[i-1][j]; 35 else if(dp[i-1][j]&gt;dp[i][j-1])f[i][j]=f[i][j-1]; 36 else f[i][j]=f[i-1][j]+f[i][j-1]; 37 } 38 } 39 printf("Case #%d: %d %d\n",k,dp[len1][len2],f[len1][len2]); 40 } 41 return 0; 42 }</pre> </div> <span class="cnblogs_code_collapse">View Code</span> <p> </p> <p> </p> <p> </p> <p><span style="font-family: 仿宋; font-size: 14pt;">到此为止,这个题已经讲解完了,接下来是笔者跟这道题的渊源。</span></p> <p><span style="font-family: 仿宋; font-size: 14pt;">我最开始接触OI是在半年前,也许有人会惊讶我半年就学到了SCS这种比较难一些的算法,我之所以学的比同年纪的人快,</span></p> <p><span style="font-family: 仿宋; font-size: 14pt;">很大程度上是和这道题有关系的。</span></p> <p><span style="font-family: 仿宋; font-size: 14pt;">我第一次看到这道题,是4个月前,是因为同社团的人为了出风头,在网上随便找了篇题解贴到了我们OJ上,结果测评过了,</span></p> <p><span style="font-family: 仿宋; font-size: 14pt;">当然,这位同学之后被老师发现了,于是就被骂了一顿。。。。</span></p> <p><span style="font-family: 仿宋; font-size: 14pt;">当时我就想,如果我能凭我的能力做出来这道题,该多么的好,于是我就开始奋斗,</span></p> <p><span style="font-family: 仿宋; font-size: 14pt;">不夸张地说,真是“夜以继日”地学;</span></p> <p><span style="font-family: 仿宋; font-size: 14pt;">在同社团的人也算是比较优秀了,到了更高一级的班学习。</span></p> <p><span style="font-family: 仿宋; font-size: 14pt;">当然,我也觉得信息学十分有乐趣,学到现在,我也不光只是想做出来这道“电子人的基因”了,还有更多,更富有挑战性,更有趣的题等着我去做。</span></p> <p><span style="font-family: 仿宋; font-size: 14pt;">但我可以说,如果没有这道题给我的激励作用,我不可能学的比现在更好。真要说起来,我还得感谢那位抄代码的同学。</span></p> <p><span style="font-family: 仿宋; font-size: 14pt;">终于, 2019-04-22 20:58:55;我做出了这道日思夜想的“电子人的基因”。</span></p> <p><span style="font-family: 仿宋; font-size: 14pt;">这就是一道“电子人的基因”的力量。</span></p> <p> </p> <div class="alert alert-success" role="alert"><p>来源:<code>https://www.cnblogs.com/szmssf/p/10758536.html</code></p></div></div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field--label">标签</div> <div class="field--items"> <div class="field--item"><a href="/tag/ganggu-0" hreflang="zh-hans">钢骨</a></div> </div> </div> Thu, 16 Jan 2020 16:05:31 +0000 两盒软妹~` 3243691 at https://www.e-learn.cn