usaco 4.1 Cryptcowgraphy(DFS+hash+剪枝)

来源:互联网 发布:php 地方门户系统 编辑:程序博客网 时间:2024/05/16 14:41

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
题目:http://ace.delos.com/usacoprob2?a=3VP4hdY1ws8&S=cryptcow

题意:给你一个字符串,要你去掉 C O W,这三个字母的同时,把C O和O W所包含的字符串对调,使得最后字符串成为题目所求

分析:这题很明显只能搜索了,不过肯定要剪枝,这种时候其实最早想到的应该是hash判重,我居然没想到,估计是太久没做题了,然后就是各种跟题目相关的剪枝,明显无解的情况都要去掉,具体就不说了,还有剪枝的顺序不同,造成的结果也是不同的这个让我爆内存n次。。。不过因此用了一个土办法,居然速度比正解快好多,hash真是个神奇的东西(就是如果hash表满了,就不保存剩下的所有状态,这样居然做到每组都是0.1S左右)=  =

代码(不会爆内存的写法,爆内存那种就不贴出来了):

/*ID: 15114582PROG: cryptcowLANG: C++*/#include<cstdio>#include<iostream>#include<cstring>using namespace std;const int mm=100007;struct hashtable{    int h[mm],p[mm],size;    char s[mm][77];    int chash(char *a)    {        int ch=0;        while(*a)ch=ch*131+(*a++);        return (ch&0x7FFFFFFF)%mm;    }    int insert(char *a)    {        int i,ch=chash(a);        for(i=h[ch];i>=0;i=p[i])            if(!strcmp(s[i],a))                return 1;        strcpy(s[size],a);        p[size]=h[ch],h[ch]=size++;        return 0;    }    int find(char *a)    {        int i,ch=chash(a);        for(i=h[ch];i>=0;i=p[i])            if(!strcmp(s[i],a))                return 1;        return 0;    }    void clear()    {        size=0;        memset(h,-1,sizeof(h));    }}g;char c[77],s[77];char ans[]="Begin the Escape execution at the Break of Dawn";bool check(){    int i,j,k,len=strlen(s);    for(i=0;i<len;++i)        if(s[i]=='C'||s[i]=='O'||s[i]=='W')break;    if(s[i]!='C')return 1;    for(i=len-1;i>=0;--i)        if(s[i]=='C'||s[i]=='O'||s[i]=='W')break;    if(s[i]!='W')return 1;    for(i=0;i<len;++i)        if(s[i]!='C'&&s[i]!='O'&&s[i]!='W')        {            for(j=i+1;j<len;++j)                if(s[j]=='C'||s[j]=='O'||s[j]=='W')break;            k=0;            while(i<j)c[k++]=s[i++];            c[k]='\0';            if(!g.find(c))return 1;        }    return 0;}bool dfs(int t){    if(t<1)    {        if(!strcmp(ans,s))return 1;        return 0;    }    int i,j,k,r,p,len=strlen(s);    char c[77];    strcpy(c,s);    for(i=0;i<len;++i)        if(c[i]=='O')            for(j=len-1;j>i;--j)                if(c[j]=='W')                    for(k=0;k<i;++k)                        if(c[k]=='C')                        {                            for(r=p=0;r<k;++r,++p)s[p]=c[r];                            for(r=i+1;r<j;++r,++p)s[p]=c[r];                            for(r=k+1;r<i;++r,++p)s[p]=c[r];                            for(r=j+1;r<len;++r,++p)s[p]=c[r];                            s[p]='\0';                            if(!strcmp(ans,s))return 1;                            if(check()||g.insert(s))continue;                            if(dfs(t-1))return 1;                        }    return 0;}int main(){char c[77];    freopen("cryptcow.in","r",stdin);    freopen("cryptcow.out","w",stdout);    int i,j,k,s1,s2,s3;    while(gets(s))    {        for(s1=s2=s3=i=0;i<strlen(s);++i)        {            if(s[i]=='C')++s1;            if(s[i]=='O')++s2;            if(s[i]=='W')++s3;        }        g.clear();        for(i=0;i<strlen(ans);++i)            for(j=i,k=0;j<strlen(ans);++j,++k)            {                if(j-i+1>=strlen(ans))break;                c[k]=ans[j];                c[k+1]='\0';                g.insert(c);            }        g.insert(s);        if(s1+s2+s3==strlen(s)-strlen(ans)&&s1==s2&&s2==s3&&dfs(s1))printf("%d %d\n",1,s1);        else puts("0 0");    }    return 0;}




原创粉丝点击