the clocks 这道题题面上是一个搜索类型的题,有9个时钟,每个时钟有4个状态,现在有9种操作,每种操作可以改变某些时钟的状态,问什么时候9个时钟都到状态0,一开始没有多想就写了个BFS,但是效率太低了,主要是深搜没有状态判重。。比如同一个操作最多就做3次,第四次做完以后就相当于没做,BFS没考虑这个的话就会陷入低效。
有了每种情况都只有3次,另外一种思路就是枚举,用到二进制位操作,程序就变得非常简洁:
对于一开始的时钟状态可以用一个二进制数表示 如 000 000 000 000 000 000 001 001 011 九个时钟每个时钟由3个bit位就可以表示。
九种操作同理用二进制表示后, 令set = 100 100 100 100 100 100 100 100 100 100 ,, (a + b) & set就是操作后的结果
操作序列同样用二进制数表示 每种操作1-3次,可以用2个bit表示那 一个 2^18的数就可以枚举完所有操作可能
/*
ID: zhangw31
PROG: clocks
LANG: C++
*/
#include <iostream>
#include <fstream>
using namespace std;
const int trans[9] = {18911232, 19136512, 2363904, 16810048, 2134536, 262657, 36936, 73, 4617};
int clears = 57521883;
int s, a, tmp, t,l;
int minl = 999999;
int main() {
ifstream fin("clocks.in");
ofstream fout("clocks.out");
for (int i = 8; i >= 0; i--) {
fin >> a;
s |= (a/3 % 4) << (3 * i);
}
for (int i = 0; i < 1048576; i++) {
tmp = s;
l = 0;
for (int j = 0; j < 9; j++) {
t = i>>2*j & 3;
tmp = (tmp + trans[j]*t) & clears;
l += t;
}
if (tmp == 0 && l < minl) {
minl = l;
a = i;
}
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < (a>>i*2&3) ; j++) {
fout << i + 1;
if (--minl) fout << " ";
else fout << endl;
}
}
}/*
Arithmetic Progressions 是一个枚举题,给定N,M,要找到N阶的p^2+q^2(p,q均小于M)集合里的等差数列
思路1 开一个一维数组用于模拟某个数是否为合格的数 + 三重for:第一层枚举起点(M^2),第二层枚举等差数列的d值(M^2),第三层枚举N;
复杂度为M^4*N,5秒内出不了结果。。。。
修正:首先枚举起点和d值的时候并不用M^2仅用枚举set里的元素和元素之间的差即可,还有一个重要的剪枝:当num[i] + (n-1)*d > max时,就不必进行N循环
/*
ID: zhangw31
PROG: ariprog
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <queue>
#include <set>
using namespace std;
int N, M;
bool isnum[250005];
int num[125005];
int count1;
ifstream fin("ariprog.in");
ofstream fout("ariprog.out");
struct Mystruct {
int start;
int progress;
Mystruct (int s, int p) : start(s), progress(p) {}
bool operator <(const Mystruct& b) const {
if (progress != b.progress) return progress > b.progress;
else return start > b.start;
}
};
priority_queue<Mystruct> q;
set<int> s;
int main()
{
fin >> N >> M;
for (int i = 0; i <= M; i++) {
for (int j = 0; j <= M; j++) {
isnum[i*i + j*j] = true;
}
}
for (int i = 0; i <= 2*M*M; i++) {
if (isnum[i]) {
num[count1++] = i;
}
}
for (int i = 0; i < count1; i++) {
for (int j = i+1; j < count1; j++) {
bool isok = true;
int d = num[j] - num[i];
if (num[i] + (N-1) * d > num[count1-1]) {
isok = false;
}
else for (int k = 2; k < N; k++) {
if (!isnum[num[i] + k*d]) {
isok = false;
break;
}
}
if (isok) {
q.push(Mystruct(num[i], d));
}
}
}
if (q.empty()) {
fout << "NONE" << endl;
}
while(!q.empty()) {
Mystruct tmp = q.top(); q.pop();
fout << tmp.start << " " << tmp.progress << endl;
}
}
Mother's Milk 三个水杯倒水的问题,abc三个水杯,abc各有一个乘水上限,问当a杯为0时,c中的水量:
一开始写了个struct+queue广搜,但是效果不好,主要是在判重方面,后面改为深搜就简洁了许多dfs(a,b,c)分别代表abc的水量,那么可以有的操作就只有
ab, ac, bc, ba, ca, cb六种,再用vis[i][j] 作为判重abc三个量,实际上是二维的变量。
/*
ID: zhangw31
PROG: milk3
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
ifstream fin("milk3.in");
ofstream fout("milk3.out");
bool visit[25][25];
bool state[25];
int maxa, maxb, maxc, count1;
void dfs(int a, int b, int c) {
if (visit[a][b]) return;
visit[a][b] = true;
if (a == 0) { state[c] = true; count1++;}
if (a + c >= maxc) dfs(a-maxc+c, b, maxc);
if (a + c < maxc) dfs(0, b, c+a);
if (a + b >= maxb) dfs(a-maxb+b, maxb, c);
if (a + b < maxb) dfs(0, b+a, c);
if (b + c >= maxc) dfs(a, b-maxc+c, maxc);
if (b + c < maxc) dfs(a, 0, c+b);
if (b + a >= maxa) dfs(maxa, b-maxa+a, c);
if (b + a < maxa) dfs(a+b, 0, c);
if (c + a >= maxa) dfs(maxa, b, c-maxa+a);
if (c + a < maxa) dfs(a+c, b, 0);
if (b + c >= maxb) dfs(a, maxb, c-maxb+b);
if (b + c < maxb) dfs(a, b+c, 0);
}
int main()
{
string ans;
fin >> maxa >> maxb >> maxc;
dfs(0, 0, maxc);
for (int i = 0; i <= 20; i++) {
if (state[i]) {
fout << i;
if (--count1)
fout << " ";
}
}
fout << endl;
}
packrec 这道题目依旧是比较暴力的一个枚举题,枚举4个矩形组合但不重合的最小面积,实际上题目已经给出了组合的所有形式,那么要做的首要工作就是如何排列,和那几个旋转,下面是一种递归排列和递归旋转的方式,当然用二进制枚举排列和旋转也可以
void rotate(int k)
{
if (k == 4) calcu();
else
{
rotate(k + 1);
swap(a[k].x, a[k].y);
rotate(k + 1);
swap(a[k].x, a[k].y);
}
}
void permutation(int level)
{
if (level == 4) rotate(0);
else {
for (int i = level; i < 4; i++) {
swap(a[level], a[i]);
permutation(level+1);
swap(a[level], a[i]);
}
}
}
1.4over