【CodeVS 2083】Cryptcowgraphy 解密牛语

http://codevs.cn/problem/2083/

奶牛搜索题。我加了如下剪枝:

1.用字符串hash判重。注意判重时也要对字符串长度判重,否则会出现两个字符串长度不同但hash值相同的情况,非常容易被卡hash。

2.先枚举O,再枚举C,W。枚举W时从后往前枚举。从网上的题解里看到的,具体为什么我也不知道(捂脸)。

3.对于所有的C,O,W字母可以将字符串切成好几段,但是无论我们怎么交换C-O之间和O-W之间的字符串,这些小段字符串是不会被分开的。所以对于每一个状态我们判断所有C,O,W切成的小段是否在目标串中出现过。这是非常厉害的剪枝。

4.剪枝3只是判断某些字符串小段是否在目标串中出现过,还可以对这些小段的第一段和最后一段加强限制。即当前串的最小的结尾字符的后一个字符是C的前缀必须是目标串的前缀,当前串最小的开头字符的前一个字符是W的后缀必须是目标串的后缀。这也是非常重要的剪枝。

有了上面四个剪枝就可以通过此题了。貌似少一个剪枝就会TLE。

搜索难在分析其玄学的复杂度QAQ

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int w = 140;
const int p = 1000007;
const char s[48] = {‘ ‘,‘B‘,‘e‘,‘g‘,‘i‘,‘n‘,‘ ‘,‘t‘,‘h‘,‘e‘,‘ ‘,‘E‘,‘s‘,‘c‘,‘a‘,‘p‘,‘e‘,‘ ‘,‘e‘,‘x‘,‘e‘,‘c‘,‘u‘,‘t‘,‘i‘,‘o‘,‘n‘,‘ ‘,‘a‘,‘t‘,‘ ‘,‘t‘,‘h‘,‘e‘,‘ ‘,‘B‘,‘r‘,‘e‘,‘a‘,‘k‘,‘ ‘,‘o‘,‘f‘,‘ ‘,‘D‘,‘a‘,‘w‘,‘n‘};

bool showed[9][p + 3];
int n, Pw[80], hash[50], step;

int gethash(int l, int r) {
	return (int) ((1ll * hash[r] - 1ll * hash[l - 1] * Pw[r - l + 1] % p + p) % p);
}

bool flag = false;

bool shown(int ha, int len) {
	for(int i = len; i <= 47; ++i)
		if (gethash(i - len + 1, i) == ha) return true;
	return false;
}

void dfs(int tmp, char *c, int tot) {
	if (tmp > step) {
		for(int i = 1; i <= 47; ++i)
			if (s[i] != c[i]) return;
		flag = true; return;
	}

	int ret = 0;
	for(int i = 1; i <= tot; ++i) ret = (int) ((1ll * ret * w + (int) c[i]) % p);
	if (showed[tmp - 1][ret]) return;
	showed[tmp - 1][ret] = true;

	ret = 1;
	while (c[ret] != ‘C‘ && c[ret] != ‘O‘ && c[ret] != ‘W‘ && ret <= tot) {
		if (c[ret] != s[ret]) ret = tot + 2;
		++ret;
	}
	if (ret == tot + 2) return;
	if (ret != tot + 1 && c[ret] != ‘C‘) return;
	ret = 0;
	while (c[tot - ret] != ‘C‘ && c[tot - ret] != ‘O‘ && c[tot - ret] != ‘W‘ && ret < tot) {
		if (c[tot - ret] != s[47 - ret]) ret = tot + 2;
		++ret;
	}
	if (ret == tot + 2) return;
	if (ret != tot && c[tot - ret] != ‘W‘) return;

	int head = 1;
	for(int i = 1; i <= tot; ++i)
		if (c[i] == ‘C‘ || c[i] == ‘O‘ || c[i] == ‘W‘) {
			if (head < i) {
				ret = 0;
				for(int j = head; j < i; ++j) ret = (int) ((1ll * ret * w + (int) c[j]) % p);
				if (!shown(ret, i - head)) return;
			}
			head = i + 1;
		}

	char ch[76];
	for(int i = 1; i <= tot; ++i)
		if (c[i] == ‘O‘)
			for(int j = 1; j < i; ++j)
				if (c[j] == ‘C‘)
					for(int k = tot; k > i; --k)
						if (c[k] == ‘W‘) {
							ret = 0;
							for(int l = 1; l < j; ++l) ch[++ret] = c[l];
							for(int l = i + 1; l < k; ++l) ch[++ret] = c[l];
							for(int l = j + 1; l < i; ++l) ch[++ret] = c[l];
							for(int l = k + 1; l <= tot; ++l) ch[++ret] = c[l];
							dfs(tmp + 1, ch, ret);
							if (flag) return;
						}
}

char c[80];

int main() {
	gets(c + 1);
	n = strlen(c + 1);
	Pw[0] = 1;
	for(int i = 1; i <= n; ++i)
		Pw[i] = (int) (1ll * Pw[i - 1] * w % p);
	hash[0] = 0;
	for(int i = 1; i <= 47; ++i)
		hash[i] = (int) ((1ll * hash[i - 1] * w + (int) s[i]) % p);

	step = (n - 47) / 3;
	dfs(1, c, n);

	if (flag) printf("%d %d\n", 1, step);
	else puts("0 0");

	return 0;
}

调了一下午+一晚上

时间: 2024-10-23 22:46:04

【CodeVS 2083】Cryptcowgraphy 解密牛语的相关文章

从磁铁到引力场,解密乐语背后的新零售密码

每每提及新零售.无界零售.第X次零售革命时,我们联想到的通常都是线上商业体系对于线下商业体系的延伸和重组.可虽然新零售以及相关概念,是由阿里.京东等电商企业率先提出的,却不代表只有线上商业体系可以主导零售模式的进化. 在今天,线下商业体系的进化无时无刻不在发生.就像在去年的中国全零售大会上,获得了2017CCFA零售创新奖的,就有以通讯零售为人所知的乐语Brookstone.在去年一年中,乐语Brookstone共有128家网红新零售店亮相,远远超过了传统零售门店的扩展速度. 在最近,我们来到了

BZOJ 1633: [Usaco2007 Feb]The Cow Lexicon 牛的词典

题目 1633: [Usaco2007 Feb]The Cow Lexicon 牛的词典 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 401  Solved: 216[Submit][Status] Description 没有几个人知道,奶牛有她们自己的字典,里面的有W (1 ≤ W ≤ 600)个词,每个词的长度不超过25,且由小写字母组成.她们在交流时,由于各种原因,用词总是不那么准确.比如,贝茜听到有人对她说"browndcodw"

洛谷P2875 [USACO07FEB]牛的词汇The Cow Lexicon

P2875 [USACO07FEB]牛的词汇The Cow Lexicon 题目描述 Few know that the cows have their own dictionary with W (1 ≤ W ≤ 600) words, each containing no more 25 of the characters 'a'..'z'. Their cowmunication system, based on mooing, is not very accurate; sometime

饥饿的奶牛(洛谷 1868)

题目描述 有一条奶牛冲出了围栏,来到了一处圣地(对于奶牛来说),上面用牛语写着一段文字. 现用汉语翻译为: 有N个区间,每个区间x,y表示提供的x~y共y-x+1堆优质牧草.你可以选择任意区间但不能有重复的部分. 对于奶牛来说,自然是吃的越多越好,然而奶牛智商有限,现在请你帮助他. 输入输出格式 输入格式: 第一行,N,如题 接下来N行,每行一个数x,y,如题 输出格式: 一个数,最多的区间数 输入输出样例 输入样例#1: 3 1 3 7 8 3 4 输出样例#1: 5 说明 1<=n<=15

动态规划 洛谷P1868 饥饿的奶牛

P1868 饥饿的奶牛 题目描述 有一条奶牛冲出了围栏,来到了一处圣地(对于奶牛来说),上面用牛语写着一段文字. 现用汉语翻译为: 有N个区间,每个区间x,y表示提供的x~y共y-x+1堆优质牧草.你可以选择任意区间但不能有重复的部分. 对于奶牛来说,自然是吃的越多越好,然而奶牛智商有限,现在请你帮助他. 输入输出格式 输入格式: 第一行,N,如题 接下来N行,每行一个数x,y,如题 输出格式: 一个数,最多的区间数 输入输出样例 输入样例#1: 3 1 3 7 8 3 4 输出样例#1: 5

程序员的生活观

在你眼里,计算机编程比父母还重要吗? 在你眼里,计算机编程比爱人和孩子还重要吗? 在你眼里,计算机编程比知己朋友还重要吗? 在你眼里,计算机编程比你的健康和生命还重要吗? 诚然,计算机编程给我们带来了无穷的乐趣:然而,任何将生命中的某一样东西看成全部的行为都将可能导致灾难性的后果.比如,女人将男人看成生命中的全部,反之亦然. 没必要一天到晚沉溺于技术的钻研中,与电脑为伴.多抽点时间出去锻炼运动,与人打交道,陪家人,联系亲友. 你需要成为一个健康的精力充沛的有活力的有思想的乐于与人沟通和协作的程序

【清北前紧急补课6】饥饿的奶牛

题目描述 有一条奶牛冲出了围栏,来到了一处圣地(对于奶牛来说),上面用牛语写着一段文字. 现用汉语翻译为: 有N个区间,每个区间x,y表示提供的x~y共y-x+1堆优质牧草.你可以选择任意区间但不能有重复的部分. 对于奶牛来说,自然是吃的越多越好,然而奶牛智商有限,现在请你帮助他. 输入输出格式 输入格式: 第一行,N,如题 接下来N行,每行一个数x,y,如题 输出格式: 一个数,最多能吃到的牧草堆数 输入输出样例 输入样例#1: 复制 3 1 3 7 8 3 4 输出样例#1: 复制 5 说明

康盛(discuz )牛逼的PHP加解密算法函数

1.前言 康盛的 authcode 函数很牛叉,是一个具有有效期的加解密函数,同一个字符每次加密所产生的结果都是不一致的,并且可以自定义设置过期时间. 设计原理:authcode 是使用异或运算进行加密和解密. 加密 明文:1010 1001 密匙:1110 0011 密文:0100 1010 得出密文0100 1010,解密之需和密匙异或下就可以了 解密 密文:0100 1010 密匙:1110 0011 明文:1010 1001 并没有什么高深的算法,密匙重要性很高,所以,关键在于怎么生成密

codevs 1405 牛的旅行x

牛的旅行 [问题描述] 农民John的农场里有很多牧区.有的路径连接一些特定的牧区.一片所有连通的牧区称为一个牧场.但是就目前而言,你能看到至少有两个牧场不连通.现在,John想在农场里添加一条路径 ( 注意,恰好一条 ).对这条路径有这样的限制:一个牧场的直径就是牧场中最远的两个牧区的距离 ( 本题中所提到的所有距离指的都是最短的距离 ).考虑如下的两个牧场,图1是有5个牧区的牧场,牧区用"*"表示,路径用直线表示.每一个牧区都有自己的坐标:   图1所示的牧场的直径大约是12.07