USACO 4.1.4 cryptcow

 题目:

http://ace.delos.com/usacoprob2?a=0H14tt2CoyP&S=cryptcow

http://pingce.ayyz.cn:9000/usaco/data/20110129214306/index.html#Section_5.1

 

Cryptcowgraphy
Brian Dean

The cows of Farmer Brown and Farmer John are planning a coordinated escape from their respective farms and have devised a method of encryption to protect their written communications.

Specifically, if one cow has a message, say, "International Olympiad in Informatics", it is altered by inserting the letters C, O, and W, in random location in the message, such that C appears before O, which appears before W. Then the cows take the part of the message between C and O, and the part between O and W, and swap them. Here are two examples:

            International Olympiad in Informatics
                              -> 
            CnOIWternational Olympiad in Informatics
            
            International Olympiad in Informatics
                              -> 
            International Cin InformaticsOOlympiad W

To make matters more difficult, the cows can apply their encryption scheme several times, by again encrypting the string that results from the previous encryption. One night, Farmer John's cows receive such a multiply-encrypted message. Write a program to compute whether or not the non-encrypted original message could have been the string:

            Begin the Escape execution at the Break of Dawn

PROGRAM NAME: cryptcow

INPUT FORMAT

A single line (with both upper and lower case) with no more than 75 characters that represents the encrypted message.

SAMPLE INPUT (file cryptcow.in)

Begin the EscCution at the BreOape execWak of Dawn

OUTPUT FORMAT

Two integers on a single line. The first integer is 1 if the message decodes as an escape message; 0 otherwise. The second integer specifies the number of encryptions that were applied (or 0 if the first integer was 0).

SAMPLE OUTPUT (file cryptcow.out)

1 1

题解:
  USACO又一道神级恶心搜索题,题意是插入COW进行加密后问能否解密。如对abcdef,加密后可变为aCdeOabWf,此即为加密方式。

  搜索吧………………………………但是必须优化啊……………………

  优化:
    1、优先枚举O的位置。
    2、检验每两个特殊字符间的字串是否为目标字串子串。
    3、不推荐链表,虽然交换是O(1)的,但不好写,也不好调,错了要哭的………………而且查找起来就有慢了………………
    4、hash判重………………这方法其实不科学,有科学的hash法,但对这道题不适用……………………

  难写,难调,如果你不想浪费时间,别写它了。如果你想练代码能力,写写吧。

View Code
  1 /*
  2 ID:zhongha1
  3 PROB:cryptcow
  4 LANG:C++
  5 */
  6 
  7 #include<cstdio>
  8 #include<cstdlib>
  9 #include<cstring>
 10 
 11 using namespace std;
 12 
 13 char goal[100]=" Begin the Escape execution at the Break of Dawn";
 14 
 15 const int mo=1000003;
 16 
 17 int sl,final;
 18 
 19 char s[100],help[100];
 20 
 21 bool hash[mo];
 22 
 23 int get_hash(char *s,int l)
 24 {
 25     int v=0,seed=131313;
 26     for (int a=1;a<=l;a++)
 27         v=(v*seed+s[a]) % mo;
 28     return (v  & 0x7FFFFFFF) % mo;
 29 }
 30 
 31 void change(char *s,int c,int o,int w,int nowl)
 32 {
 33     memset(help,0,sizeof(help));
 34     int l=0;
 35     for (int a=1;a<c;a++)
 36     {
 37         l++;
 38         help[l]=s[a];
 39     }
 40     for (int a=o+1;a<w;a++)
 41     {
 42         l++;
 43         help[l]=s[a];
 44     }
 45     for (int a=c+1;a<o;a++)
 46     {
 47         l++;
 48         help[l]=s[a];
 49     }    
 50     for (int a=w+1;a<=nowl;a++)
 51     {
 52         l++;
 53         help[l]=s[a];
 54     }
 55     strcpy(s+1,help+1);
 56 }
 57 
 58 bool cut(char *s,int l)
 59 {
 60     int nowl=0;
 61     int fp=1;
 62     while (s[fp]!='C' & s[fp]!='O' && s[fp]!='W')
 63     {
 64         if (s[fp]!=goal[fp]) return true;
 65         fp++;
 66     }
 67     if (s[fp]!='C') return true;
 68     int lp=l,hehe=47;
 69     while (s[lp]!='C' && s[lp]!='O' && s[lp]!='W')
 70     {
 71         if (s[lp]!=goal[hehe]) return true;
 72         lp--;
 73         hehe--;
 74     }
 75     if (s[lp]!='W') return true;
 76     int lastp=fp,nowp=fp+1;
 77     while (nowp<=lp)
 78     {
 79         if (s[nowp]=='C' || s[nowp]=='O' || s[nowp]=='W')
 80         {
 81             nowl=0;
 82             for (int a=lastp+1;a<nowp;a++)
 83             {
 84                 nowl++;
 85                 help[nowl]=s[a];
 86             }
 87             bool exist=false;
 88             for (int a=1;a+nowl-1<=47;a++)
 89             {
 90                 for (int b=1;b<=nowl;b++)
 91                     if (help[b]!=goal[a+b-1]) break;
 92                     else
 93                     {
 94                         if (b==nowl) exist=true;
 95                     }
 96                 if (exist) break;
 97             }
 98             if (lastp+1!=nowp)
 99                 if (!exist) return true;
100             lastp=nowp;
101         }
102         nowp++;
103     }
104     return false;
105 }
106 
107 bool dfs(char *s,int d)
108 {
109     int nowv=get_hash(s,sl-d*3);
110     if (hash[nowv]) return false;
111     if (nowv==final) return true;
112     hash[nowv]=true;
113     if (cut(s,sl-d*3)) return false;
114     char help[100];
115     for (int o=1;o<=sl-d*3;o++)
116         if (s[o]=='O')
117         {
118             for (int c=1;c<o;c++)
119                 if (s[c]=='C')
120                 {
121                     for (int w=sl-d*3;w>o;w--)
122                         if (s[w]=='W')
123                         {
124                             strcpy(help+1,s+1);
125                             change(help,c,o,w,sl-d*3);
126                             if (dfs(help,d+1)) return true;
127                         }
128                 }
129         }
130     return false;
131 }
132 
133 int main()
134 {
135     freopen("cryptcow.in","r",stdin);
136     freopen("cryptcow.out","w",stdout);
137 
138     int nowl=0;
139     char orz='!';
140     while (orz!='\r' && orz!='\n')
141     {
142         scanf("%c",&orz);
143         nowl++;
144         s[nowl]=orz;
145     }
146     s[nowl]='\0';
147     nowl--;
148     sl=nowl;
149     final=get_hash(goal,47);
150     if ((nowl-47)%3!=0)
151     {
152         printf("0\n");
153         return 0;
154     }
155     if (dfs(s,0)) printf("1 %d\n",(nowl-47)/3);
156     else printf("0 0\n");
157 
158     return 0;
159 }

 




转载于:https://www.cnblogs.com/zhonghaoxi/archive/2012/06/29/2570506.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值