题意:
2块矩形巧克力 如果边长可以整除2 则可以从一半出掰开 吃掉一半 如果可以整除3 则可以从1/3处掰开 吃掉1/3 问 最少吃几次 能使得2块面积相同 输出最后时刻的边长
思路:
面积最多只有10^18 因此形成的面积的种类数最多几万种 我们可以利用面积来暴搜出所有状态 然后找面积相同时的最少步数
PS:数论的方法更好
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
using namespace std;
typedef long long LL;
#define N 1000010
int a[2], b[2];
map<LL, int> res[2];
map<LL, pair<int, int> > way[2];
map<LL, int>::iterator it1, it2;
struct node {
int x, y;
} f1, f2;
queue<node> q;
int ans;
LL fzc;
int main() {
LL u, v;
int now;
scanf("%d%d%d%d", &a[0], &b[0], &a[1], &b[1]);
res[0][(LL) (a[0]) * b[0]] = 0;
res[1][(LL) (a[1]) * b[1]] = 0;
way[0][(LL) (a[0]) * b[0]] = make_pair(a[0], b[0]);
way[1][(LL) (a[1]) * b[1]] = make_pair(a[1], b[1]);
for (int i = 0; i <= 1; i++) {
f1.x = a[i];
f1.y = b[i];
q.push(f1);
while (!q.empty()) {
f1 = q.front();
u = (LL) (f1.x) * f1.y;
q.pop();
now = res[i][u];
if (u % 2 == 0) {
v = u / 2;
if (!res[i].count(v)) {
res[i][v] = now + 1;
if (f1.x % 2 == 0) {
f2.x = f1.x / 2;
f2.y = f1.y;
} else {
f2.x = f1.x;
f2.y = f1.y / 2;
}
way[i][v] = make_pair(f2.x, f2.y);
q.push(f2);
}
}
if (u % 3 == 0) {
v = u / 3 * 2;
if (!res[i].count(v)) {
res[i][v] = now + 1;
if (f1.x % 3 == 0) {
f2.x = f1.x / 3 * 2;
f2.y = f1.y;
} else {
f2.x = f1.x;
f2.y = f1.y / 3 * 2;
}
way[i][v] = make_pair(f2.x, f2.y);
q.push(f2);
}
}
}
}
ans = -1;
for (it1 = res[0].begin(), it2 = res[1].begin();
it1 != res[0].end() && it2 != res[1].end();) {
if ((*it1).first == (*it2).first) {
if (ans == -1 || (*it1).second + (*it2).second < ans) {
ans = (*it1).second + (*it2).second;
fzc = (*it1).first;
}
it1++;
it2++;
} else if ((*it1).first > (*it2).first)
it2++;
else
it1++;
}
printf("%d\n", ans);
if (ans >= 0) {
pair<int, int> tp1 = way[0][fzc], tp2 = way[1][fzc];
printf("%d %d\n", tp1.first, tp1.second);
printf("%d %d\n", tp2.first, tp2.second);
}
return 0;
}