这个其实我没过。。。QAQ,但是好久没做出来题目了,就放宽一点时限嘻嘻,求不喷。
原题地址:http://cdqz.openjudge.cn/noip/1009/
题目描述
一个发送机可以通过一条隧道发送一些以二进制代码组成的单词。在其尽头的接收机可以使用特殊技术恢复到最初的单词。每个单词最初都由0和1组成。所有的单词最-初长度都为n(4≤N ≤l000)。当穿过隧道之后单词可能发生以下几种情况之一:
(1)任意(一个)0被1取代
(2)任意(一个)符号被删除
(3)一个符号(0或1)被插入到任何位置
(4)不改变
我们知道最初的单词都具有以下性质:有1的位置号的总和是N+1的倍数,或者是0.
Input
N和转换后的单词,每个单词占一行。单词数不大于2001,不会有其它任何东西,除了一些空格与空行。
Output
你的程序应该打印输出原始序列的词,注意换行: 。
若有多解,操作4优先,不行则按操作1,2,3优先。同一操作,按操作位置最先的优先(从左到右数起l,2,3,…N),还有操作2时,被删数列,先在被删数列添0,不行再添1。如果没答案输出-1
Sample Input
4
0000
011
1011
11011
Sample Output
0000
0110
1001
1111
附注(嘻嘻----)
思路
本来我一直在想各种BFS滴。后来才发现只做一步,是的,只做一步,成败只有一步,简单了一点儿,然后又发现了一个亮点:对于每个密文只需要输出一个明文即可,所以O(2000*1000^2*4)后来我才发现这里1000是有平方的(ORZ)............算了,过一些是一些吧。。。
代码
//后面pluscheck分成1,2是因为题目规定一定要先添加0后添加1,只好copy一遍了。。。。 //2014-7-8 08:32:35 #include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> using namespace std; int N,M; int y[1005]; char str[1005]; int HIGHEST_CALLS; void ccout() //-----普通输出----- { if ((HIGHEST_CALLS==1)) return; for (int i=1;i<=M;i++) cout<<y[i];cout<<endl; HIGHEST_CALLS=1; } void check() //-----普通检查----- { if (HIGHEST_CALLS==1) return; int i; int flag=0; for (i=1;i<=M;i++) {if (y[i]==1) flag+=i; } if ((flag%N)==0) {ccout(); HIGHEST_CALLS=1;exit;} } void pluscheck1(int x) //-----有一个0被删除了----- { if (HIGHEST_CALLS==1) return; int i; int flag=0; for (i=1;i<=M;i++) { if (y[i]==1) { flag+=i; if (i>=x) flag++; } } if ((flag%N)==0) { for (int i=1;i<x;i++) cout<<y[i]; cout<<'0'; for (int i=x;i<=M;i++) cout<<y[i]; cout<<endl; HIGHEST_CALLS=1; exit; } } void pluscheck2(int x) //-----有一个1被删除了----- { if (HIGHEST_CALLS==1) return; int i; int flag=0; for (i=1;i<=M;i++) { if (y[i]==1) { flag+=y[i]; if (i>=x) flag++; } } if (((flag+x)%N)==0) { for (int i=1;i<x;i++) cout<<y[i]; cout<<'1'; for (int i=x;i<=M;i++) cout<<y[i]; cout<<endl; HIGHEST_CALLS=1; exit; } } void reductioncheck(int x) //-----一个符号(0或1)被插入到任何位置----- { if (HIGHEST_CALLS==1) return; int i; int flag=0; for (i=1;i<x;i++) {if (y[i]==1) flag+=i;} for (i=x+1;i<=M;i++) {if (y[i]==1) flag+=i-1;} if ((flag%N)==0) { for (i=1;i<x;i++)cout<<y[i]; for (i=x+1;i<=M;i++) cout<<y[i];cout<<endl; HIGHEST_CALLS=1;exit;} } int main() { //freopen("word.in","r",stdin); //freopen("word.out","w",stdout); int i,j,k,a,b,c; cin>>N; N++; //-----主要是懒得把所有N都-1了----- while (cin>>str) { HIGHEST_CALLS=0; //-----最高指令:判断是否已经输出过解了。----- M=strlen(str); for (i=1;i<=M;i++) { y[i]=int(str[i-1])-int('0'); } if (((N-1)==M)&&(HIGHEST_CALLS==0)) //-----判定自己是不是问题----- { check(); } if (((N-1)==M)&&(HIGHEST_CALLS==0)) //-----有个0变成了1问题----- { for (i=1;i<=M;i++) { if (y[i]==1) {y[i]=0; check(); y[i]=1;} } } if (((N-2)==M)&&(HIGHEST_CALLS==0)) //-----删除了一个符号问题----- { for (i=1;i<=M+1;i++) pluscheck1(i); for (i=1;i<=M+1;i++) pluscheck2(i); } if ((N==M)&&(HIGHEST_CALLS==0)) //-----插入了一个符号问题----- { for (i=1;i<=M;i++) reductioncheck(i); } if (HIGHEST_CALLS==0) cout<<"-1"<<endl; } return 0; } //2014-7-8 13:45:14
评测结果
时限被我放宽到每个点15s才过了,我想哭。。。。还需要进一步的优化哇。。。。