题目

题目描述

农夫John的牛从农场逃脱出去了,所以他决定用一个密码锁来把农场的门锁起来,这个密码锁有三个表盘,每个表盘都是环形的,而且上面刻有1~N,现在John设了一个开锁密码,而且这个锁的设计者也有一个开锁密码。这个锁有一个特点,那就是它的容错方式,当我们输入密码时,如果我们的密码与正确的开锁密码相比较,对应的每一个表盘上的数字的距离都相差不超过2时,这个密码便可以打开这个锁。

例如:John设定的开锁密码为(1,2,3),锁的设计者的开锁密码为(4,5,6)。如果我们现在将锁设定为(1,3,5),那么这个密码也可以将这个锁打开,因为我们的密码相对于John的密码每一个表盘上的数字的距离分别为0, 1, 2,没有超过2的距离,所以可以打开。如果我们的密码是(2,4,8),那么同样这个密码对于锁设计者的密码来说,每个表盘上的数字距离分别为2,1,2,所以这个密码也是可以打开的。但是如果我们的密码是(1,5,6),这个密码对于John的密码距离分别为0,3,3,对于设计者的密码距离分别为3,0,0,都存在距离超过2的情况,所以这个密码无法打开这把锁。

现在我们设定一个N,然后输入John的密码与设计者的密码,需要我们计算出有多少种密码是可以打开这把锁的。

数据范围

1 <= N <= 100

样例输入

50

1 2 3

5 6 7

样例输出

249

解题思路

我们用最暴力的方法是可以解决这个问题的,因为这个题目的数据量不是很大,我们可以枚举每一种可能的密码,然后一一判断这个密码是否能够打开这把锁。当然这种方法的时间复杂度是比较高的,对于数据量比较大的时候可能不合适。

解题代码

/*
ID: yinzong2
PROG: combo
LANG: C++11
*/
#define MARK
#include<cstdio>
#include<cstring>
#include<cstdlib> using namespace std;
const int MAXN = 100+10; int n;
int farmer[3], master[3];
bool vis[MAXN][MAXN][MAXN]; bool ok(int a, int b) {
if(abs(a-b) <= 2 || abs(a-b) >= n-2) return true;
return false;
} int main() {
#ifdef MARK
freopen("combo.in", "r", stdin);
freopen("combo.out", "w", stdout);
#endif // MARK
while(~scanf("%d", &n)) {
memset(vis, false, sizeof(vis));
for(int i = 0; i < 3; i++) {
scanf("%d", &farmer[i]);
}
for(int i = 0; i < 3; i++) {
scanf("%d", &master[i]);
}
int ans = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
for(int k = 1; k <= n; k++) {
if(!vis[i][j][k]) {
if((ok(i, farmer[0]) && ok(j, farmer[1]) && ok(k, farmer[2]))
|| (ok(i, master[0]) && ok(j, master[1]) && ok(k, master[2]))) {
ans++;
vis[i][j][k] = true;
}
}
}
}
}
printf("%d\n", ans);
}
return 0;
}

解题思路(Type 2)

我们可以利用排列组合的公式来计算,首先我们对John的密码进行分析,这个密码能够产生多少种开锁密码。显然,由John的密码推导出的开锁密码的数量与设计者的密码推导出的开锁密码数量是一样多的,证明我就省略了。然后关键的一步就是去重,因为我们之前统计的John密码推导出来的开锁密码可能会与设计者密码推导出来的开锁密码重复,我们需要将重复的去掉,最终就是我们的结果。

这种解法的关键在于,我们需要利用乘法原理来计算总共有多少,还有就是去重的计算,最后还有我们对于环形表盘的处理,如果计算距离。这种解法可以将时间复杂度降到最低,优化到O(1),是一种非常不错的算法。

解题代码(Type 2)

/*
ID: yinzong2
PROG: combo
LANG: C++11
*/
#define MARK
#include<cstdio> using namespace std; int n;
int farmer[3][5], master[3][5]; int makeNumber(int id, int val, int a[3][5]) {
int cnt = 0;
int temp;
for(int i = -2; i <= 2; i++) {
temp = val + i;
while(temp <= 0) temp += n;
while(temp > n) temp -= n;
bool flag = true;
for(int j = 0; j < cnt; j++) {
if(temp == a[id][j]) {
flag = false;
break;
}
}
if(flag) {
a[id][cnt++] = temp;
}
}
return cnt;
} int testNumber(int id, int val, int a[3][5], int len1) {
int cnt = 0;
int len2 = makeNumber(id, val, a);
for(int i = 0; i < len2; i++) {
for(int j = 0; j < len1; j++) {
if(master[id][i] == farmer[id][j]) {
cnt++;
break;
}
}
}
return cnt;
} int main() {
#ifdef MARK
freopen("combo.in", "r", stdin);
freopen("combo.out", "w", stdout);
#endif // MARK
while(~scanf("%d", &n)) {
int x;
int cnt1;
for(int i = 0; i < 3; i++) {
scanf("%d", &x);
cnt1 = makeNumber(i, x, farmer);
}
int sum = cnt1*cnt1*cnt1*2;
int cnt2[3];
for(int i = 0; i < 3; i++) {
scanf("%d", &x);
cnt2[i] = testNumber(i, x, master, cnt1);
}
sum -= (cnt2[0] * cnt2[1] * cnt2[2]);
printf("%d\n", sum);
}
return 0;
}

USACO Section 1.3 Combination Lock 解题报告的更多相关文章

  1. USACO Section1.3 Combination Lock 解题报告

    combo解题报告 —— icedream61 博客园(转载请注明出处)---------------------------------------------------------------- ...

  2. USACO Section 1.3 Prime Cryptarithm 解题报告

    题目 题目描述 牛式的定义,我们首先需要看下面这个算式结构: * * * x * * ------- * * * <-- partial product 1 * * * <-- parti ...

  3. USACO Section 1.4 Arithmetic Progressions 解题报告

    题目 题目描述 现在给你一个数集,里面的数字都是由p^2+q^2这种形式构成的0 <= p,q <= M,我现在需要你在其中找出一个长为N的等差数列,数列中的第一个数字为a,公差为b,当你 ...

  4. USACO Section 1.3 Barn Repair 解题报告

    题目 题目描述 某农夫有一个养牛场,所有的牛圈都相邻的排成一排(共有S个牛圈),每个牛圈里面最多只圈养一头牛.有一天狂风卷积着乌云,电闪雷鸣,把牛圈的门给刮走了.幸运的是,有些牛因为放假,所以没在自己 ...

  5. USACO Section 1.3 Mixing Milk 解题报告

    题目 题目描述 Merry Milk Makers 公司的业务是销售牛奶.它从农夫那里收购N单位的牛奶,然后销售出去.现在有M个农夫,每个农夫都存有一定量的牛奶,而且每个农夫都会有自己的定价.假设所有 ...

  6. USACO Section 1.2 Dual Palindromes 解题报告

    题目 题目描述 有一些数(如 21),在十进制时不是回文数,但在其它进制(如二进制时为 10101)时就是回文数. 编一个程序,从文件读入两个十进制数N.S.然后找出前 N 个满足大于 S 且在两种以 ...

  7. USACO Section 1.2 Palindromic Squares 解题报告

    题目 题目描述 输入一个基数B,现在要从1到300之间找出一些符合要求的数字N.如果N的平方转换成B进制数之后是一个回文串,那么N就符合要求.我们将N转换成B进制数输出,然后再将N的平方转换成B进制数 ...

  8. USACO Section 1.2 Milking Cows 解题报告

    题目 题目描述 有3个农夫每天早上五点钟便起床去挤牛奶,现在第一个农夫挤牛奶的时刻为300(五点钟之后的第300个分钟开始),1000的时候结束.第二个农夫从700开始,1200结束.最后一个农夫从1 ...

  9. USACO Section 1.1 Broken Necklace 解题报告

    题目 题目描述 有一串项链,它是由红蓝白三种颜色的珠子组成的,b代表蓝色,w代表白色,r代表红色,当它完整的时候是一个闭合的环形.现在它在某一个节点断裂了,之前的环形也随之变成了直线形.从两端开始收集 ...

随机推荐

  1. 字符串长度截取换行/n

    /// <summary>        /// 格式化字符串长度,超出部分显示省略号,区分汉字跟字母.汉字2个字节,字母数字一个字节        /// </summary> ...

  2. 华为配置SSH登陆详细步骤

    理解下SSH登录的过程: 1.建立目的端口为22的TCP连接 2.协商SSH版本 3.协商密钥和算法 4.会话建立 下面为server端的详细配置步骤: 1.创建本地RSA密钥对 rsa local- ...

  3. 2.2 Xpath-helper (chrome插件) 爬虫、网页分析解析辅助工具

    1. Xpath-helper下载 可以直接在chrome浏览器中的扩展程序搜索 Xpath-helper进行添加 也可以直接在http://www.chromein.com/crx_11654.ht ...

  4. validator验证

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...

  5. Chapter 2 Open Book——19

    He bent over and began scraping together a pile of the white mush. 他弯下腰,开始团起一个白色的雪球. "I'll see ...

  6. thinkphp的目录结构设计经验总结1

    ---恢复内容开始--- 用thinkphp开发了好些项目了:最近准备抽空写一些经验总结: 希望能给刚开始接触tp的童鞋们提供一些开发的方案:少走一些弯路:少踩一些坑: 这些绝对都是些精华干货:耐着性 ...

  7. elasticsearch快照和恢复

    摘要:es可以通过简单的命令对索引或者整个集群进行快照和恢复 快照和恢复 Snapshot and restore 模块允许创建单个索引或者整个集群的快照到远程仓库. 在初始版本里只支持共享文件系统的 ...

  8. AngularJs多重视图和路由的使用

    使用AngularJs来做多重视图和路由是在方便不过了,在开发过程中,都有许多的页面,而这些页面都有相同的部分,比如页面的头部和尾部通常都是一样的,变化的都是主体部分,还有就是一些后端管理的一些项目, ...

  9. 运行出第一个程序Hello World、第二个程序网页浏览器

    很长时间没有发博客记录我的奋斗历程了,原因不外乎遇到了对我而言“巨大的”困难. 经历了长期的找不到合适的教材.找不到Xcode资源.运行不出例程的痛苦以后,近日终于走上正轨. 现在补发一个过去2个月来 ...

  10. excel中自动变为插入语句的写法

    =concatenate("insert into t(b,c) values('",b1,"','",c1,"');")