1 条题解
-
0
前言:
-
菜鸡 HydroKomide 在 CSP-S 与 WC 双双打铁,于是一怒之下开始爆肝非传统题目。
-
目前,这是一篇非 AC 题解,目前分数为 93pts(
毕竟这种玄学题目需要经过大量调参才能 A)。 -
本篇题解未完待续。
思路:
第一篇题解的想法很神,切成长度为 的小块在能够保证正确率的情况下使空间消耗尽量小。
但是存储数字的那一步略显多余。我们考虑:怎样在不存具体数字的情况下最大化正确率?
此处省略机房大辩论 字。
我们发现,扫描到一个三段字符时,只有可能发生以下两种情况:
- 使某一篇文章权值提高。
- 使某一或两篇文章不可能为答案(即完全排除可能性)。
而这两种信息可以直接用两个字符维护。
举例:一段信息为
abc24。其中,
2代表给 号文章加权值。4二进制为100,即完全排除 号文章。这样,当我们扫描到
abc这个子串,直接加权值、排除文章即可。说这么多,具体实现呢?
文本分析使用了多个程序逐步推进,相对比较复杂但思路顺畅。
首先是拆解原文。把文章中每类的三连字符都计算个数。当然,由于文章长度不同,字符的相对权值肯定要乘上一个系数。
这里使用了
map:#include<cstdio> #include<fstream> #include<map> #include<iostream> using namespace std; map<string,int>mp; char a,b,c; int main(){ freopen("文章名.txt","r",stdin); freopen("ANALYZE_文章名.txt","w",stdout); string str=" "; scanf("%c%c%c",&a,&b,&c); do{ str[0]=a,str[1]=b,str[2]=c; mp[str]++;//每扫描一个字符存一次 a=b,b=c; }while(scanf("%c",&c)!=EOF); for(char i='!';i<='z';i++) for(char j='!';j<='z';j++) for(char k='!';k<='z';k++){//枚举所有可能性,这里省略了空格 string sss=" "; sss[0]=i,sss[1]=j;sss[2]=k; if(mp[sss]!=0)cout<<sss<<" "<<mp[sss]*文章系数<<"\n"; } return 0; }每篇文章都用这个程序跑一遍,得到三个包含字符 + 相对权值的文本文档。
然后就是生成数据库了。把三个分析结果的文本文档都读一遍,然后用上文所提的思路存储下来。
为了更高的准确率,我们需要设定一个阈值系数,即容错率。确保一篇文章的相对权值显著高于另两篇文章。这里设为 。
#include<fstream> #include<map> #include<cstring> #include<iostream> #define ri register int using namespace std; const double COR=1.6;//阈值系数 map<string,int>Smp,Mmp,Pmp; string str; int cnt; int main(){ freopen("PROGRAM.txt","w",stdout); ifstream Sin("ANALYZE_S.txt"); ifstream Min("ANALYZE_M.txt"); ifstream Pin("ANALYZE_P.txt");//上个程序生成的文档 while(Sin>>str){ Sin>>cnt; Smp[str]=cnt; } while(Min>>str){ Min>>cnt; Mmp[str]=cnt; } while(Pin>>str){ Pin>>cnt; Pmp[str]=cnt;//全部读入map } for(char i='!';i<='z';i++) for(char j='!';j<='z';j++) for(char k='!';k<='z';k++){ string sss=" "; sss[0]=i,sss[1]=j,sss[2]=k; int del=0,pls=0; double S=0,M=0,P=0; if(Smp.count(sss)!=0)S=Smp[sss]; if(Mmp.count(sss)!=0)M=Mmp[sss]; if(Pmp.count(sss)!=0)P=Pmp[sss]; if(S==0&&M==0&&P==0)continue; if(S==0)del|=(1<<2); if(M==0)del|=(1<<1); if(P==0)del|=(1<<0);//如果文章权值为0,即可完全排除这篇文章 if(S>M*COR&&S>P*COR)pls=1; if(M>S*COR&&M>P*COR)pls=2; if(P>S*COR&&P>M*COR)pls=3;//确保阈值 if(pls==0&&del==0)continue; printf("%c%c%c%d%d",i,j,k,pls,del); } return 0; }当然,由于我们带上了标点符号,所以还要在生成的所有双引号前加上
\。最后结果是这样一个东西。所以能够提交的程序也就来了:link
后记:
玄学题目是最好骗分、最具思维性,但最不容易 AC 的一类题目,同时也最贴近日常应用的。
所以为什么 OI 反而不考这一类呢?当然,还没用高进制压缩就有 35KB 的长度,这也给后续的工作留下了空间。经对拍,在 长度为 左右时本代码正确率显著劣于题解的 AC 代码。下一步可以考虑存一些长段的语句辅助判断,或者对于长句子使用哈希。
有错误欢迎评论指正,其他好思路欢迎与 HydroKomide 私信讨论(
THE END
-
- 1
信息
- ID
- 2369
- 时间
- 5000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者