微电子的小菜逼也开始刷软件题了,今年第一轮我错过了,准备参加剩下的三轮考试,拿第一轮的题目练练手
这道题出处http://code.google.com/codejam/contest/3214486/dashboard
大意是小明买了七段数码管连在倒计时器上,结果发现数码管中有些地方坏了永远不显示,给出一系列单个数码管倒计时显示结果,有些位数本该是1,但因为故障永远为0。输入显示结果序列,输出下一个预计显示结果,如果之前序列永远不可能出现,或者根据输入无法准确预测下一个显示结果(有模棱两可值),则显示ERROR
下面是我写的程序,内含注释
#include<vector>
#include<iostream>
#include<queue>
#include <string>
#include <fstream>
#include <time.h>
using namespace std;
//七段码
__int8 seg[10] = {
0X7E,
0X30,
0X6D,
0X79,
0X33,
0X5B,
0X5F,
0X70,
0X7F,
0X7B
};
int main() {
int begin = clock();
ifstream fin("A-large-practice.in");
ofstream fout("output.txt");
int T, N;
__int8 history[100];
char buffer[8];
fin >> T;
for (int t = 1; t <= T; t++) {
fin >> N;
int result;//当前结果
bool match = false;//该序列是否有对应倒计数值
int globalresult;//之前结果
__int8 broken;//确定坏的位
__int8 good;//确定好的位
__int8 unsure;//模棱两可的位
bool err = false;
for (int i = 0; i < N; i++) {
fin >> buffer;
__int8 display = 0;
for (int j = 0; j < 7; j++) {
display <<= 1;
display |= (buffer[j] == '1' ? 1 : 0);
}
history[i] = display;
//对于长输入序列,如果其周期不为10,则可以直接在输入阶段判定有错而不用执行后面的判断
if (i >= 10 && history[i-10] != history[i]) {
err = true;
}
}
if (err) {
fout << "Case #" << t << ": ERROR!" << endl;
continue;
}
//从0~9试验倒计数起始值
for (int start = 0; start < 10; start++) {
broken = 0;
good = 0;
bool fail = false;
//由于之前已经确定序列以10为周期循环,所以最多只需要测10个输入即可
for (int i = 0; i < 10 && i < N; i++) {
good |= history[i];//亮过的位一定是好的
__int8 expect = seg[(start - i + 10) % 10];//预计当前显示
broken |= (expect & ~history[i]);//该亮但不亮的位是坏的
unsure = ~good & ~broken & 0X7F;
//如果好位和坏位有重叠,或者不该亮的位亮了,说明该起始值设置有错
if ((good & broken) != 0 || ((history[i] & ~(expect & good)) != 0)) {
fail = true;
break;
}
}
if (!fail) {
result = seg[(start - N % 10 + 10) % 10] & ~broken;//预计下一个输出
//如果下一个输出有模棱两可的地方,或者与之前已经计算出的下一个显示不同,则报ERROR
if (((result & unsure) != 0) || (match && (result != globalresult))) {
match = false;
break;
} else {
globalresult = result;
match = true;
}
}
}
//如果下一个显示有且只有一个,则输出下一个显示结果,否则报ERROR
if (match) {
fout << "Case #" << t << ": ";
for (int i = 6; i >= 0; i--) {
fout << ((result & 1 << i) != 0 ? 1 : 0);
}
fout << endl;
} else {
fout << "Case #" << t << ": ERROR!" << endl;
}
}
cout << clock() - begin << endl;
return 0;
}
对长输入序列做了些优化,而且是用位操作,这个程序跑起来还是挺快的,就是位操作很搞脑子,智商不够用了,写了大半天才跑通