pushbox-quest/optimizer/box-breaker.cpp
szdytom e3703197a9
upload files
Signed-off-by: szdytom <szdytom@qq.com>
2024-01-18 09:40:37 +08:00

282 lines
6.1 KiB
C++

#include <bits/stdc++.h>
using namespace std;
const int n = 20;
const int q_siz = 20;
const double keep_p = 0.97;
mt19937 mt(114514);
uniform_real_distribution<> d01(0, 1);
struct Question {
bitset<20> M[20];
int sx, sy, tx, ty, bx, by;
};
Question start_question;
namespace Solve {
bitset<20> mp[20];
int dis[20][20][20][20];
queue<tuple<int, int, int, int>> qu;
inline int bfs(int px, int py, int bx, int by, int tx, int ty) {
memset(dis, 127, sizeof(dis));
while (!qu.empty())
qu.pop();
auto expand = [&](int npx, int npy, int nbx, int nby, int d) {
if (npx < 0 || npx >= n)
return;
if (npy < 0 || npy >= n)
return;
if (nbx < 0 || nbx >= n)
return;
if (nby < 0 || nby >= n)
return;
if (mp[npx][npy] == 0)
return;
if (mp[nbx][nby] == 0)
return;
if (npx == nbx && npy == nby)
return;
if (dis[npx][npy][nbx][nby] <= d)
return;
dis[npx][npy][nbx][nby] = d;
qu.emplace(npx, npy, nbx, nby);
};
expand(px, py, bx, by, 0);
while (!qu.empty()) {
auto [npx, npy, nbx, nby] = qu.front();
int d = dis[npx][npy][nbx][nby];
qu.pop();
// cout<<"Now player at ( "<<npx<<" , "<<npy<<" ) and box at ( "<<nbx<<"
// , "<<nby<<" ) and dis = "<<d<<endl;
if (nbx == tx && nby == ty)
return d;
expand(npx + 1, npy, nbx, nby, d + 1);
expand(npx - 1, npy, nbx, nby, d + 1);
expand(npx, npy + 1, nbx, nby, d + 1);
expand(npx, npy - 1, nbx, nby, d + 1);
if (npx + 1 == nbx && npy == nby)
expand(npx + 1, npy, nbx + 1, nby, d + 1);
if (npx - 1 == nbx && npy == nby)
expand(npx - 1, npy, nbx - 1, nby, d + 1);
if (npx == nbx && npy + 1 == nby)
expand(npx, npy + 1, nbx, nby + 1, d + 1);
if (npx == nbx && npy - 1 == nby)
expand(npx, npy - 1, nbx, nby - 1, d + 1);
}
return -1;
}
inline int solve(Question q) {
memcpy(mp, q.M, sizeof(q.M));
return bfs(q.sx, q.sy, q.bx, q.by, q.tx, q.ty);
}
}; // namespace Solve
vector<pair<Question, int>> prq, nwq;
inline void constructMain() {
auto expand = [&](Question q) {
if (q.sx < 0 || q.sx >= n)
return;
if (q.sy < 0 || q.sy >= n)
return;
if (q.bx < 0 || q.bx >= n)
return;
if (q.by < 0 || q.by >= n)
return;
if (q.tx < 0 || q.tx >= n)
return;
if (q.ty < 0 || q.ty >= n)
return;
if (q.M[q.sx][q.sy] == 0)
return;
if (q.M[q.bx][q.by] == 0)
return;
if (q.M[q.tx][q.ty] == 0)
return;
int d = Solve::solve(q);
nwq.push_back({q, d});
};
auto expandAll = [&](Question q) {
expand(q);
q.sx--;
expand(q);
q.sx++;
q.sx++;
expand(q);
q.sx--;
q.sy--;
expand(q);
q.sy++;
q.sy++;
expand(q);
q.sy--;
q.bx--;
expand(q);
q.bx++;
q.bx++;
expand(q);
q.bx--;
q.by--;
expand(q);
q.by++;
q.by++;
expand(q);
q.by--;
q.tx--;
expand(q);
q.tx++;
q.tx++;
expand(q);
q.tx--;
q.ty--;
expand(q);
q.ty++;
q.ty++;
expand(q);
q.ty--;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
q.M[i][j] = !q.M[i][j];
expand(q);
q.M[i][j] = !q.M[i][j];
}
}
Question q1 = q;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int x = (d01(mt) <= 0.3);
q1.M[i][j] = q1.M[i][j] ^ x;
if ((i == q1.sx && j == q1.sy) || (i == q1.bx && j == q1.by)
|| (i == q1.tx && j == q1.ty))
q1.M[i][j] = 1;
}
}
expand(q1);
};
prq.push_back({start_question, Solve::solve(start_question)});
for (int _ = 1;; _++, swap(prq, nwq)) {
for (pair<Question, int> pr : prq)
expandAll(pr.first);
sort(nwq.begin(),
nwq.end(),
[&](const pair<Question, int>& a, const pair<Question, int>& b) {
return a.second > b.second;
});
vector<pair<Question, int>> tmp(0);
double nwpw = 1;
for (int i = 0; i < nwq.size(); i++) {
if (d01(mt) <= nwpw)
tmp.push_back(nwq[i]);
nwpw *= keep_p;
}
nwq = tmp;
if (_ % 1 == 0) {
cout << "Iterated for " << _ << " times" << endl;
Question mxq = nwq.front().first;
cout << "Max step = " << nwq.front().second << endl;
// cout<<"***************************"<<endl;
// for(int i=0;i<n;i++)
// {
// for(int j=0;j<n;j++)
// {
// if(i==mxq.sx&&j==mxq.sy) cout<<"P";
// else if(i==mxq.tx&&j==mxq.ty) cout<<"O";
// else if(i==mxq.bx&&j==mxq.by) cout<<"*";
// else if(mxq.M[i][j]==0) cout<<"#";
// else cout<<".";
// }
// cout<<endl;
// }
// cout<<"***************************"<<endl;
fstream fou("nowmax.txt", ios::out);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == mxq.sx && j == mxq.sy)
fou << "P";
else if (i == mxq.tx && j == mxq.ty)
fou << "O";
else if (i == mxq.bx && j == mxq.by)
fou << "*";
else if (mxq.M[i][j] == 0)
fou << "#";
else
fou << ".";
}
fou << endl;
}
fou.close();
system("cp nowmax.txt nowmax-cp.txt");
}
}
}
inline void init() {
fstream fin("nowmax.txt", ios::in);
for (int i = 0; i < n; i++) {
string s;
fin >> s;
for (int j = 0; j < n; j++) {
if (s[j] == '#')
start_question.M[i][j] = 0;
else
start_question.M[i][j] = 1;
if (s[j] == 'P')
start_question.sx = i, start_question.sy = j;
if (s[j] == '*')
start_question.bx = i, start_question.by = j;
if (s[j] == 'O')
start_question.tx = i, start_question.ty = j;
}
}
// cout<<"Start question : *********************"<<endl;
// for(int i=0;i<n;i++)
// {
// for(int j=0;j<n;j++)
// {
// cout<<start_question.M[i][j];
// }
// cout<<endl;
// }
// cout<<"sx = "<<start_question.sx<<" , sy = "<<start_question.sy<<endl;
// cout<<"bx = "<<start_question.bx<<" , by = "<<start_question.by<<endl;
// cout<<"tx = "<<start_question.tx<<" , ty = "<<start_question.ty<<endl;
// cout<<"**************************************"<<endl;
fin.close();
}
int main() {
init();
// cout<<Solve::solve(start_question)<<endl;
constructMain();
}