因为一天机房都是断网状态,校内的小V评测这道题总显示Unaccept,所以下午放学后就和xiaoyimi晚上回家自习,来做一做这道题。

搜索+剪枝优化:

一开始我是顺着低位向高位填数,这么暴力在Vijos上有90分,如果NOIP能得这么多分我也甘心就写这个暴力吧

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int s1[27], s2[27], an[27], ans[27], n;
bool vis[27], pd = 0;
inline void dfs1(int, int);
inline void dfs3(int tmp, int delta) {
int c = an[tmp];
if (ans[c] == -1) {
int num = (ans[s1[tmp]] + ans[s2[tmp]] + delta), mo = num % n;
if (!vis[mo]) {
vis[mo] = 1;
ans[c] = mo;
dfs1(tmp + 1, num / n);
if (pd) return;
vis[mo] = 0;
ans[c] = -1;
}
} else {
int num = (ans[s1[tmp]] + ans[s2[tmp]] + delta);
if (ans[c] == num % n)
dfs1(tmp + 1, num / n);
if (pd) return;;
}
}
inline void dfs2(int tmp, int delta) {
int c = s2[tmp];
if (ans[c] == -1) {
for(int i = 0; i < n; ++i)
if (!vis[i]) {
vis[i] = 1;
ans[c] = i;
dfs3(tmp, delta);
if (pd) return;
vis[i] = 0;
ans[c] = -1;
}
} else {
dfs3(tmp, delta);
if (pd) return;
}
}
inline void dfs1(int tmp, int delta) {
if (tmp > n){
if (delta == 0)
pd = 1;
return;
}
int c = s1[tmp];
if (ans[c] == -1) {
for(int i = 0; i < n; ++i)
if (!vis[i]) {
vis[i] = 1;
ans[c] = i;
dfs2(tmp, delta);
if (pd) return;
vis[i] = 0;
ans[c] = -1;
}
} else {
dfs2(tmp, delta);
if (pd) return;
}
}
int main() {
scanf("%d\n", &n);
char c;
for(int i = n; i > 0; --i) {
c = getchar();
s1[i] = c - 'A';
}
scanf("\n");
for(int i = n; i > 0; --i) {
c = getchar();
s2[i] = c - 'A';
}
scanf("\n");
for(int i = n; i > 0; --i) {
c = getchar();
an[i] = c - 'A';
}
for(int i = 0; i < n; ++i)
ans[i] = -1;
dfs1(1, 0);
for(int i = 0; i < n; ++i)
printf("%d ",ans[i]);
return 0;
}

正解:先扫出字母出现的先后顺序,在这个扫出的序列上暴力,每次暴力后简单的扫一遍整个等式进行$check$,这是我写的唯一的也是最重要的剪枝,能过掉那组T掉的数据:

输入

20 
NLHFIEASBRQJOGKMDPCT 
NQGPSIIGKDMFDCBFMQSO 
PNKNTOLHEIJHFGJKHJGG

输出

18 14 0 9 15 17 7 13 12 16 1 10 4 2 8 5 11 3 6 19

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int s1[27], s2[27], an[27], ans[27], n, tb[27], tn = 0;
bool vis[27], pan = 0;
inline void mktb(int x) {
if (!vis[x]){
vis[x] = 1;
tb[++tn] = x;
}
}
inline bool pd() {
bool p = 0;
int delta = 0;
for(int i = 1; i <= n; ++i){
int a = ans[s1[i]], b = ans[s2[i]], c = ans[an[i]];
if (a == -1 || b == -1) {
p = 1;
} else {
if (c == -1) {
if (p) {
if (a + b == n-1)
p = 1;
else
p = 0, delta = (a + b) / n;
} else {
p = 0;
delta = (a + b + delta) /n;
}
} else {
if (p) {
if ((a + b) % n == c) {
p = 0;
delta = (a + b) / n;
} else if ((a + b + 1) % n == c) {
p = 0;
delta = (a + b + 1) / n;
} else
return 1;
} else {
if ((a + b + delta) % n != c)
return 1;
else {
p = 0;
delta = (a + b + delta) / n;
}
}
}
}
}
if (!p && delta == 1)
return 1;
else
return 0;
}
inline void dfs(int tmp) {
if (pd())
return;
if (tmp > n) {
pan = 1;
return;
}
for(int i = 0; i < n; ++i)
if (!vis[i]) {
vis[i] = 1;
ans[tb[tmp]] = i;
dfs(tmp + 1);
if (pan)
return;
vis[i] = 0;
ans[tb[tmp]] = -1;
}
}
int main() {
scanf("%d\n", &n);
char c;
for(int i = n; i > 0; --i) {
c = getchar();
s1[i] = c - 'A';
}
scanf("\n");
for(int i = n; i > 0; --i) {
c = getchar();
s2[i] = c - 'A';
}
scanf("\n");
for(int i = n; i > 0; --i) {
c = getchar();
an[i] = c - 'A';
}
for(int i = 1; i <= n; ++i) {
mktb(s1[i]);
mktb(s2[i]);
mktb(an[i]);
}
for(int i = 0; i < n; ++i)
vis[i] = 0, ans[i] = -1;
dfs(1);
for(int i = 0; i < n; ++i)
printf("%d ",ans[i]);
return 0;
}

没了,,,xyx和我玩了一下午的棋盘类游戏,SG什么的真的不会啊,省选要爆0了TwT

【NOIP 2004】虫食算的更多相关文章

  1. NOIP 2004 虫食算题解

    问题 E: [Noip2004]虫食算 时间限制: 1 Sec  内存限制: 128 MB 题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一 ...

  2. Codevs 1064 虫食算 2004年NOIP全国联赛提高组

    1064 虫食算 2004年NOIP全国联赛提高组 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 所谓虫食算,就是原先的算式 ...

  3. 虫食算 2004年NOIP全国联赛提高组(dfs)

    1064 虫食算 2004年NOIP全国联赛提高组  时间限制: 2 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Descrip ...

  4. 深度优先搜索 codevs 1064 虫食算

    codevs 1064 虫食算 2004年NOIP全国联赛提高组  时间限制: 2 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description 所 ...

  5. 洛谷 P1092 虫食算 Label:dfs

    题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +8468#6633 44445509678 其中# ...

  6. codevs1064 虫食算

    题目描述 Description 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045    +    8468#6 ...

  7. NOIP2004 虫食算

    描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子:43#9865#045+ 8468#6633= 44445506678其中#号代表 ...

  8. Luogu P1092 虫食算

    题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +8468#6633 44445509678 其中# ...

  9. 【NOIP2004】【CJOJ1703】【洛谷1092】虫食算

    题面 题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +8468#6633 44445509678 ...

  10. 【NOIP2004】虫食算

    Description 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +. 8468#6633 444455 ...

随机推荐

  1. 怎样运用好ZBrush中的布尔运算

     我们知道DynaMesh常用于基础模型的起稿到中模的制作,它是ZBrush ® 4R2新增的功能,其强大的功能除了对模型进行重新布线,还可以进行布尔运算.配合Insert笔刷进行布尔运算,可以做出Z ...

  2. Codeforces 410C.Team[构造]

    C. Team time limit per test 1 second memory limit per test 256 megabytes input standard input output ...

  3. Sass关于颜色函数的乐趣

    阅读目录 1. 了解RGB和HSL颜色标准 2. RGB函数 3. HSL函数 4. Opacity函数 5. 其他颜色函数 6. 一个简单的应用 在Sass中,定义了很多现成的函数,可供我们使用.在 ...

  4. Vector3 *2 ,ToString()自动四舍五入

    还以为出错了,仔细看发现ToString()自动四舍五入 Vector3 forward = Camera.main.transform.forward; Debug.Log("forwar ...

  5. maven-安装配置

    Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具. maven是什么maven这个词可以翻译为“知识的积累”,也可以翻译为“专家”或“内行” ...

  6. C++ ODB 框架(未实践使用)

    http://www.codesynthesis.com/products/odb/doc/manual.xhtml#17.1

  7. svn恢复被删除的分支 svn del 分支

    笔者不小心,在操作时,删除了一个主开发分支(main_dev). 一. 悲剧的语句: svn del  -m"1.误删除分支"  http://svr_path/branches/ ...

  8. offsetParent详解

    offsetParent与parentNode一样,都是获取父节点,但是offsetParent却有很大的不同之处: offsetParent找有定位的父节点,没有定位默认是body,ie7以下定位在 ...

  9. Linux中 groupadd 和 useradd 的命令说明

    groupadd [options] group 说明The groupadd command creates a new group account using the values specifi ...

  10. git工作区、暂存区、版本库之间的关系

    区分三者关系 Git最让你迷惑的无非是它里面的各种概念了,如果是刚开始接触Git希望看完本篇介绍之后有一个清晰的认识,笔者认识也有限这里只说说个人对使用Git的感受,说一下它里面的几个最常用的概念的理 ...