Cryptcowgraphy[需重做]

题意:比较长,直接摘抄NOCOW翻译(http://www.nocow.cn/index.php/Translate:USACO/cryptcow

描述

农民Brown和John的牛们计划协同逃出它们各自的农场。它们设计了一种加密方法用来保护它们的通讯不被他人知道。

如果一头牛有信息要加密,比如"International Olympiad in Informatics",它会随机地把C,O,W三个字母插到到信息中(其中C在O前面,O在W前面),然后它把C与O之间的文字和 O与W之间的文字的位置换过来。这里是两个例子:

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

为了使解密更复杂,牛们会在一条消息里多次采用这个加密方法(把上次加密的结果再进行加密)。一天夜里,John的牛们收到了一条经过多次加密的信息。请你写一个程序判断它是不是这条信息经过加密(或没有加密)而得到的:

Begin the Escape execution at the Break of Dawn

[编辑]格式

PROGRAM NAME:cryptcow

INPUT FORMAT:

(file cryptcow.in)

一行,不超过75个字符的加密过的信息。

OUTPUT FORMAT:

(file cryptcow.out)

一行,两个整数. 如果能解密成上面那条逃跑的信息,第一个整数应当为1,否则为0;如果第一个数为1,则第二个数表示此信息被加密的次数,否则第二个数为0。

[编辑]SAMPLE INPUT

Begin the EscCution at the BreOape execWak of Dawn

[编辑]SAMPLE OUTPUT

1 1

解题思路

  1. 基本完全参考NOCOW上的思想和c代码(http://www.nocow.cn/index.php/Code:USACO/cryptcow/C),等做完Section4再来重新搞一下

代码

/*
ID: zc.rene1
LANG: C
PROG: cryptcow
 */

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define CINDEX 3
#define OINDEX 15
#define WINDEX 23

FILE *fout;
char dest[48] = "Begin the Escape execution at the Break of Dawn";
char in[76];
int position[53][54];
int total_depth;
char elf[1253][30][76];

int GetNum(char c)
{
    if (c == ' ') 
    {
	return 0;
    }
    else if ((c <= 'Z') && (c >= 'A'))
    {
	return c - 'A' + 1;
    }
    else if ((c <= 'z') && (c >= 'a'))
    {
	return c - 'a' + 27;
    }
    else
    {
	return -1;
    }
}

int GetDepth(void)
{
    int letter_num_dest[53];
    int letter_num_in[53];
    int i, j, ret;

    memset(letter_num_dest, 0, 53 * sizeof(int));
    memset(letter_num_in, 0, 53 * sizeof(int));
    memset(position, 0, 53 * 54 * sizeof(int));

    for (i=0; i<strlen(dest); i++)
    {
	j = GetNum(dest[i]);
	if (j == -1)
	{
	    return -1;
	}
	position[j][0]++;
	position[j][position[j][0]] = i;
	letter_num_dest[j]++;
    }

    for (i=0; i<strlen(in); i++)
    {
	j = GetNum(in[i]);
	if (j == -1)
	{
	    return -1;
	}
	letter_num_in[j]++;
    }
    
    ret = letter_num_in[CINDEX];
    if (ret != letter_num_in[OINDEX])
    {
	return -1;
    }
    if (ret != letter_num_in[WINDEX])
    {
	return -1;
    }

    letter_num_in[CINDEX] = 0;
    letter_num_in[OINDEX] = 0;
    letter_num_in[WINDEX] = 0;

    if (memcmp(letter_num_in, letter_num_dest, 53) != 0)
    {
	return -1;
    }
    return ret;
}

void Swap(char *key, int a, int b, int c)
{
    int len = strlen(key);
    int i;
    char cp[76];

    for (i=0; i<a; i++)
    {
	cp[i] = key[i];
    }
    for (i=0; i<c - b - 1; i++)
    {
	cp[a + i] = key[b + i + 1];
    }
    for (i=0; i<b - a - 1; i++)
    {
	cp[a + c - b - 1 + i] = key[a + i + 1];
    }
    for (i=0; i<len - 1 - c; i++)
    {
	cp[c - 2 + i] = key[c + i + 1];
    }
    cp[c - 2 + i] = '\0';
    strcpy(key, cp);
}

long ELFHash(char *key)
{
    long h = 0;
    while (*key)
    {
	h = (h << 4) + *key;
	key++;
	long g = h & 0Xf0000000L;
	if (g)
	{
	    h ^= g >> 24;
	}
	h &= ~g;
    }
    return h % 1253;
}

int Check(char *key)
{
    int i = -1, j = -1, k;

    while(key[++i] != 'C')
    {
	if (key[i] != dest[i])
	{
	    return 0;
	}
    }
    while (key[++j]) ;

    i = 47;
    while (key[--j] != 'W')
    {
	if (key[j] != dest[--i])
	{
	    return 0;
	}
    }
    
    i = -1;
    while (key[++i] != 'C') ;
    k = i + 1;
    j = 1;
    while (key[++i])
    {
	if (key[i] == 'C' || key[i] == 'O' || key[i] == 'W')
	{
	    j = 1;
	    k = i + 1;
	    continue;
	}
	if (key[i] != dest[position[GetNum(key[k])][j] + i - k])
	{
	    j++;
	    i = k -1;
	    if (j > position[GetNum(key[k])][0])
	    {
		return 0;
	    }
	}
    }
    return 1;
}

void Search(char *key, int depth)
{
    int i, j, k, f, g;
    char cp[76];

    for (j=0; j<strlen(key); j++)
    {
	if (key[j] == 'O')
	{
	    for (i=j; i>=0; i--)
	    {
		if (key[i] == 'C')
		{
		    for (k=strlen(key)-1; k>j; k--)
		    {
			if (key[k] == 'W')
			{
			    strcpy(cp, key);
			    Swap(cp, i, j, k);
			    if (depth == total_depth)
			    {
				if (strcmp(cp, dest) == 0)
				{
				    fprintf(fout, "1 %d\n", total_depth);
				    exit(0);
				}
			    }
			    if (Check(cp))
			    {
				f = ELFHash(cp);
				g = 0;
				while (elf[f][g][0] != 0)
				{
				    if (strcmp(elf[f][g], cp) == 0) break;
				    g++;
				}
				if (elf[f][g][0] == 0)
				{
				    strcpy(elf[f][g], cp);
				    Search(cp, depth + 1);
				}
			    }
			}
		    }
		}
	    }
	}
    }
}

int main(void)
{
    FILE *fin;

    fin = fopen("cryptcow.in", "r");
    fout = fopen("cryptcow.out", "w");

    fgets(in, 76, fin);
    in[strlen(in) - 1] = '\0';
    
    if (strlen(in) >= strlen(dest) && (strlen(in) - strlen(dest)) % 3 == 0)
    {
	if (strcmp(in, dest) == 0)
	{
	    fprintf(fout, "1 0\n");
	    return 0;
	}
	total_depth = GetDepth();
	if (total_depth == -1)
	{
	    fprintf(fout, "0 0\n");
	    return 0;
	}
	Search(in, 1);
    }
    fprintf(fout, "0 0\n");
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值