Submission #669946
Source Code Expand
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <cassert>
#include <functional>
#include <numeric>
#include <limits>
#include <tuple>
using namespace std;
#define all(c) (c).begin(), (c).end()
#define iter(c) __typeof((c).begin())
#define cpresent(c, e) (find(all(c), (e)) != (c).end())
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define tr(c, i) for (iter(c) i = (c).begin(); i != (c).end(); ++i)
#define pb(e) push_back(e)
#define mp(a, b) make_pair(a, b)
namespace HK {
const int MAX_LR = 32 * 32 * 105;
int L, R;
vector<int> adj[MAX_LR];
bool vis[MAX_LR], usd[MAX_LR];
int lev[MAX_LR + 1], mat[MAX_LR];
bool augment(int l) {
if (l == L) return true;
if (vis[l]) return false;
vis[l] = true;
rep (i, adj[l].size()) {
int r = adj[l][i], l2 = mat[r];
if (lev[l2] > lev[l] && augment(l2)) {
mat[r] = l;
return true;
}
}
return false;
}
int bipartite_matching() {
fill(mat, mat + R, L);
memset(usd, 0, sizeof(bool) * L);
bool update;
do {
fill(lev, lev + L + 1, -1);
lev[L] = R;
queue<int> que;
rep (l, L) if (!usd[l]) {
que.push(l);
lev[l] = 0;
}
while (!que.empty()) {
int l = que.front();
que.pop();
rep (i, adj[l].size()) {
int r = adj[l][i], l2 = mat[r];
if (lev[l2] < 0) {
lev[l2] = lev[l] + 1;
que.push(l2);
}
}
}
memset(vis, 0, sizeof(bool) * L);
update = false;
rep (l, L) if (!usd[l] && augment(l)) usd[l] = update = true;
} while (update);
return count(usd, usd + L, true);
}
} // namespace HK
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};
int N = 30;
int A[40][40];
int vbase[40][40];
int vid(int x, int y, int a) {
return vbase[y][x] + (a - 1);
}
const int MAX_P = 100010;
int P, pid[MAX_P];
vector<vector<tuple<int, int, int>>> paths;
bool pdone[MAX_P];
vector<int> pfwd[MAX_P], pbwd[MAX_P];
int pcrrdeg[MAX_P], crrA[40][40];
int num_pdone = 0;
void output_path(int p) {
assert(pcrrdeg[p] == 0);
for (auto t : paths[p]) {
int x = get<0>(t), y = get<1>(t);
printf("%d %d\n", y, x);
--crrA[y][x];
}
for (int q : pbwd[p]) --pcrrdeg[q];
pdone[p] = true;
++num_pdone;
}
void output_path_recursive(int p) {
if (pdone[p]) return;
pdone[p] = true;
for (auto q : pfwd[p]) output_path_recursive(q);
output_path(p);
}
int match(std::function<bool(int, int, int, int)> f) {
int s = 0;
for (int y = 1; y <= N; ++y) {
for (int x = 1; x <= N; ++x) {
vbase[y][x] = s;
s += A[y][x];
}
}
HK::L = HK::R = s;
rep (l, HK::L) HK::adj[l].clear();
for (int y = 1; y <= N; ++y) {
for (int x = 1; x <= N; ++x) {
for (int a = 2; a <= A[y][x]; ++a) {
rep (d, 4) {
int tx = x + dx[d], ty = y + dy[d];
if (a - 1 <= A[ty][tx] && f(x, y, tx, ty)) {
HK::adj[vid(x, y, a)].push_back(vid(tx, ty, a - 1));
}
}
}
}
}
return HK::bipartite_matching();
}
int mdist(int x, int y, int tx, int ty) {
return abs(x - tx) + abs(y - ty);
}
int main(int argc, char **argv) {
if (argc != 1) N = atoi(argv[1]);
for (int y = 1; y <= N; ++y) {
for (int x = 1; x <= N; ++x) {
scanf("%d", &A[y][x]);
}
}
//
// Bipartite matching
//
match([&](int x, int y, int tx, int ty) -> bool {
return x + y < tx + ty;
});
//
// Decompose
//
memset(pid, -1, sizeof(pid));
for (int a = 1; a <= 110; ++a) {
for (int y = 1; y <= N; ++y) {
for (int x = 1; x <= N; ++x) {
if (a > A[y][x]) continue;
int &p = pid[vid(x, y, a)];
if (p == -1) {
p = paths.size();
paths.emplace_back();
}
paths[p].emplace_back(x, y, a);
pid[HK::mat[vid(x, y, a)]] = p; // parent
}
}
}
P = paths.size();
for (auto &p : paths) reverse(all(p));
fprintf(stderr, "Num of paths: %d\n", P);
fprintf(stderr, "Point: %d\n", 100000 - P);
//
// Graph
//
rep (p, P) {
for (auto t : paths[p]) {
int x, y, a;
tie(x, y, a) = t;
if (a + 1 <= A[y][x]) {
int q = pid[vid(x, y, a + 1)];
assert(p != q);
pfwd[p].pb(q);
pbwd[q].pb(p);
}
}
}
rep (p, P) pcrrdeg[p] = pfwd[p].size();
//
// Greedy reconnection
//
int num_happy = 0;
for (int y = 1; y <= N; ++y) for (int x = 1; x <= N; ++x) crrA[y][x] = A[y][x];
while (num_pdone < P) {
// Starting position
int x, y;
{
vector<tuple<double, int, int, int>> ps;
for (int y = 1; y <= N; ++y) {
for (int x = 1; x <= N; ++x) {
int a = crrA[y][x], p = pid[vid(x, y, a)];
if (paths[p][0] != make_tuple(x, y, a) || pcrrdeg[p] != 0) continue;
ps.emplace_back(a - x, rand(), x, y);
}
}
assert(!ps.empty());
sort(ps.rbegin(), ps.rend());
tie(x, y) = make_pair(get<2>(ps[0]), get<3>(ps[0]));
}
int a = crrA[y][x];
// Greedy
for (;;) {
int p = pid[vid(x, y, a)];
assert(paths[p][0] == make_tuple(x, y, a));
output_path(p);
{
auto t = paths[p].back();
x = get<0>(t);
y = get<1>(t);
a = get<2>(t);
}
if (a == 1) break;
vector<int> ds(4);
iota(all(ds), 0);
random_shuffle(all(ds));
rep (i, 4) {
int d = ds[i];
int tx = x + dx[d], ty = y + dy[d], ta = a - 1;
if (ta != crrA[ty][tx]) continue;
int tp = pid[vid(tx, ty, ta)];
if (paths[tp][0] != make_tuple(tx, ty, ta)) continue;
if (pdone[tp] || pcrrdeg[tp] > 0) continue;
tie(x, y, a) = make_tuple(tx, ty, ta);
goto found;
}
break;
found:
++num_happy;
}
}
return 0;
}
Submission Info
Submission Time
2016-03-20 21:02:10+0900
Task
A - 高橋君の山崩しゲーム
User
iwiwi
Language
C++14 (GCC 5.4.1)
Score
889119
Code Size
6242 Byte
Status
AC
Exec Time
374 ms
Memory
12028 KB
Compile Error
./Main.cpp: In function ‘int main(int, char**)’:
./Main.cpp:162:28: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
scanf("%d", &A[y][x]);
^
Judge Result
Set Name
test_01
test_02
test_03
test_04
test_05
test_06
test_07
test_08
test_09
test_10
Score / Max Score
89217 / 100000
88844 / 100000
88962 / 100000
88713 / 100000
88929 / 100000
88642 / 100000
89266 / 100000
88783 / 100000
88807 / 100000
88956 / 100000
Status
Set Name
Test Cases
test_01
subtask_01_01.txt
test_02
subtask_01_02.txt
test_03
subtask_01_03.txt
test_04
subtask_01_04.txt
test_05
subtask_01_05.txt
test_06
subtask_01_06.txt
test_07
subtask_01_07.txt
test_08
subtask_01_08.txt
test_09
subtask_01_09.txt
test_10
subtask_01_10.txt
Case Name
Status
Exec Time
Memory
subtask_01_01.txt
AC
350 ms
11780 KB
subtask_01_02.txt
AC
353 ms
12028 KB
subtask_01_03.txt
AC
374 ms
11776 KB
subtask_01_04.txt
AC
368 ms
12020 KB
subtask_01_05.txt
AC
374 ms
11900 KB
subtask_01_06.txt
AC
366 ms
11904 KB
subtask_01_07.txt
AC
346 ms
11896 KB
subtask_01_08.txt
AC
370 ms
11776 KB
subtask_01_09.txt
AC
366 ms
11900 KB
subtask_01_10.txt
AC
368 ms
11900 KB