以下是问题陈述的链接:http://train.usaco.org/usacoprob2?a=ZSMwtXwq7ro&S=combo Problem Statement。
编辑1:问题是这样的: 有一个锁,锁有2个有效的3位数组合。由用户设置的另一个是由制造商设置的主密钥。此外,锁具有一定的误差容限,即即使表盘上的数字分别位于有效组合的最多2个位置,它也会打开。
例如,假设用户设置密钥为1,2,3,主密钥(制造商设置)为4,5,6。对于这2个密钥,1,3,5是有效密钥,因为每个数字之间的差异此键和用户设置键的(在相同位置)至少为2 。但是,1,5,6是无效的组合,因为该键和用户组键的数字之间的差异> 2,主密钥相同。
基本上我正在做的事情非常天真,我正在生成所有可能的锁定组合并检查每个组合的有效性。这是我的代码
import java.util.*;
public class combo {
public static void main(String[] args){
Scanner myScanner = new Scanner(System.in);
int N = myScanner.nextInt();
int[] keys = new int[3];
int[] masterKeys = new int[3];
for(int i = 0; i < 3; i++){
keys[i] = myScanner.nextInt();
}
for(int i = 0; i < 3; i++){
masterKeys[i] = myScanner.nextInt();
}
int cnt = 0;
int[] combo = new int[3];
for(int i = 1; i <= N; i++){
combo[0] = i;
for(int j = 1; j <= N; j++){
combo[1] = j;
for(int k = 1; k <=N; k++){
combo[2] = k;
if(validCombo(combo, keys, masterKeys)){
cnt += 1;
}
}
}
}
System.out.println(cnt);
}
// bug here
/*
Valid
combo : 1, 3, 5
key : 1, 2, 3
master 4, 5, 6
Invalid
1 5 6
*/
public static boolean validCombo(int[] combo, int[] keys, int[] masterKeys){
boolean checkKeys = true;
boolean checkMasterKeys = true;
for(int i = 0; i < 3; i++){
if(Math.abs((int)(combo[i]-keys[i])) > 2){
checkKeys = false;
}
if(Math.abs((int)(combo[i]-masterKeys[i])) > 2){
checkMasterKeys = false;
}
}
return checkKeys | checkMasterKeys;
}
}
因此,对于输入N = 50,键= 1,2,3和masterKeys = 5,6,7,我得到输出184但是正确的输出是249(给定测试用例的样本)。任何人都可以请给我一个关于我的逻辑错误的提示
答案 0 :(得分:1)
你没有考虑到数字环绕的事实 - 即,当N = 50时,那么50与1,2相距1,远离2,等等。
当尝试调试这样的东西时,如果你打印出你的程序正在计算的解决方案,然后比较问题网站上列出的输出,如果他们给你这些细节,或者只是使用额外信息,以验证您自己的思维过程。
答案 1 :(得分:0)
而不是&#34;尝试&#34;您可以计算它们的所有组合
计算每个刻度盘的重叠数量
如果键号与主键号之间的距离为
is >= 5 --> you have 10 distinct values
is < 5 --> you have (5 - distance) overlapping numbers
例子:
key: 3 master key: 8 distinct numbers: 10 = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
key: 3 master key: 6 distinct numbers: 8 = 1, 2, 3, 4, 5, 6, 7, 8
4 and 5 are the overlapping numbers for this dial
如果至少有一个表盘没有重叠数字,那么我们最多有250个组合
max. number - overlapping combinations
示例:key:3,4,5主密钥:7,8,9
1 2 3 -+
2 3 4 |
3 4 5 |<-- the combinations close to the key
4 5 6 |
5 6 7 -+<-- the only overlapping number
6 7 8 |
7 8 9 |<-- the combinations close to the master key
9 10 11 |
10 11 12 -+
There are 249 valid combinations.
这是一个简短的计算片段。
int numbersPerDail = 50;
int dials = 3;
int[] keys = {2, 2, 3};
int[] masterKeys = {48, 5, 6};
int[] overlappingNumbers = new int[dials];
for (int i = 0; i < dials; i++) {
int distance = Math.max(keys[i], masterKeys[i]) - Math.min(keys[i], masterKeys[i]);
if (distance >= 46) { // the dial is circular
distance = numbersPerDail - distance;
}
overlappingNumbers[i] = 5 - distance;
}
int doubleCombos = 0;
if (overlappingNumbers[0] > 0 && overlappingNumbers[1] > 0 && overlappingNumbers[2] > 0) {
doubleCombos = overlappingNumbers[0] * overlappingNumbers[1] * overlappingNumbers[2];
}
System.out.println("valid combinations = " + (250 - doubleCombos));