因为一天机房都是断网状态,校内的小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. JAVA IO 以及 NIO 理解

    由于Netty,了解了一些异步IO的知识,JAVA里面NIO就是原来的IO的一个补充,本文主要记录下在JAVA中IO的底层实现原理,以及对Zerocopy技术介绍. IO,其实意味着:数据不停地搬入搬 ...

  2. 原生的强大DOM选择器querySelector

    在传统的 JavaScript 开发中,查找 DOM 往往是开发人员遇到的第一个头疼的问题,原生的 JavaScript 所提供的 DOM 选择方法并不多,仅仅局限于通过 tag, name, id ...

  3. 1.使用using释放资源

    using语句有二个关键字 >>作为关键字,using可以导入命名空间 >>作为C#语句,using可以释放对象占用的内存资源 语法: using(SqlConnection ...

  4. Flex:自定义滚动条样式/隐藏上下箭头

    Flex组件自定义滚动条的实现 .scrollBar{ downArrowUpSkin:Embed(source="img/mainLeftScrollBar/bar_bottom.png& ...

  5. [No000046]为什么跳槽加薪会比内部调薪要高?

    有网友在知乎提问: 最近在思考一个问题,为什么跳槽往往意味着加薪? 如果一个人确有价值,为什么在原来的公司没有在薪水上体现出来?如果没有价值,为什么跳槽以后就会加薪?还是可以单纯的解释为,应聘者和招聘 ...

  6. eclipse打不开,报错 "java was started with exit code=13"

    刚才打开eclipse时,出现如上的报错窗口. 1.查看java 版本,发现是1.8版本,记得自己之前手动安装的java应该是1.7或者更低的版本.让我想起之前系统总是会提醒java有更新,最近就没有 ...

  7. Visual Studio各版本工程文件之间的转换

    转载于:http://www.cnblogs.com/jmliao/p/5594179.html 由于VS版本比较多,低版本无法直接打开高版本的工程文件,通过对工程文件进行一些修改可以解决这些问题. ...

  8. Centos5.8 安装 ImageMagick 6.8.9-3

    下载最新的ImageMagick源码包 ImageMagick-6.8.9-3.x86_64.rpm 直接prm -ivh 安装提示错误 error: Failed dependencies: lib ...

  9. BZOJ 1082 【SCOI2005】 栅栏

    Description 农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材.于是农夫约翰到木材店购买木材.可是木材店老板说他这里只剩下少部分大规格的木板了.不过约翰可以购买这些木 ...

  10. MakeCode 递归生成资源文件

    static void yieldDir(DirectoryInfo dir, int depth, StringBuilder sb1, StringBuilder sb2) { var first ...