Submission #669579
Source Code Expand
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<climits>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<queue>
#include<deque>
#include<algorithm>
#include<utility>
#include<complex>
#include<functional>
#include<cassert>
#include<set>
#include<stack>
const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
namespace btk{
#define MP make_pair
#define row second.first
#define column second.second
using RESULT=pair<int,pair<int,int>>;
const int d4[]={0,-1,0,1,0};
int cnt[30][30];
RESULT cnt2[30][30];
vector<pair<int,int>> getMaxLength(const vector<vector<int>>& v){
int max_val=0;
fill((int*)cnt,(int*)cnt+30*30,-1);
for(int r = 0; r < 30; r++)
for(int c = 0; c < 30; c++)
cnt2[r][c]=RESULT(-1,MP(r,c));
for(int r = 0; r < 30; r++)
for(int c = 0; c < 30; c++)
max_val=max(v[r][c],max_val);
if(max_val==1)
for(int r = 0; r < 30; r++)
for(int c = 0; c < 30; c++)if(max_val==v[r][c])return vector<pair<int,int>>{MP(r,c)};
//座標をチェックするラムダ
auto check=[](int r,int c){return 0<=r&&r<30&&0<=c&&c<30;};
//再帰ラムダ
std::function<int(int,int)> dfs=[&](int r,int c){
if(cnt[r][c]!=-1)return cnt[r][c];
cnt[r][c]=1;
if(v[r][c]==1)return 1;
for(int i = 0; i < 4; i++){
int nr=r+d4[i],nc=c+d4[i+1];
if(check(nr,nc)&&
v[nr][nc]==v[r][c]-1){
cnt[r][c]=max(cnt[r][c],dfs(nr,nc)+1);
}
}
return cnt[r][c];
};
std::function<RESULT(int,int)> dfs2=[&](int r,int c){
if(cnt2[r][c].first!=-1)return cnt2[r][c];
cnt2[r][c].first=dfs(r,c);
if(v[r][c]==1)return cnt2[r][c];
for(int i = 0; i < 4; i++){
int nr=r+d4[i],nc=c+d4[i+1];
if(check(nr,nc)&&
v[nr][nc]==v[r][c]-1){
auto sub=dfs2(nr,nc);
if(sub.second==MP(nr,nc))sub.second=MP(r,c);
sub.first++;
cnt2[r][c]=max(cnt2[r][c],sub);
}
if(v[r][c]>=4&&check(nr,nc)&&v[nr][nc]==v[r][c]){
auto sub=MP(dfs(nr,nc)+1,MP(nr,nc));
cnt2[r][c]=max(cnt2[r][c],sub);
}
}
return cnt2[r][c];
};
RESULT top(-1,pair<int,int>());
for(int r = 0; r < 30; r++)
for(int c = 0; c < 30; c++)
if(v[r][c]==max_val){
top=max(dfs2(r,c),top);
}
vector<pair<int,int>> res;
res.push_back(top.second);
while(true){
unsigned prevsize=res.size();
for(int i = 0; i < 4; i++){
int nr=top.row+d4[i],nc=top.column+d4[i+1];
if(check(nr,nc)&&
v[nr][nc]==v[top.row][top.column]-1&&
cnt[nr][nc]==cnt[top.row][top.column]-1){
top.second=MP(nr,nc);
res.push_back(top.second);
break;
}
}
if(res.size()==prevsize)break;
}
return res;
}
};
const int MAX = 30;
const int BEAM_WIDTH = 200;
int A[MAX][MAX];
struct State {
State(int h, int w) : height(h), width(w), sum(0) {
board.resize(height);
for (int i = 0; i < height; i++) board[i].resize(width);
}
// 盤面
vector<vector<int> > board;
// 盤面の高さ, 幅
int height, width;
// 盤面の和
int sum;
// 評価値のメモ
int value;
// 評価関数
int eval() const;
// 今の状態で最も長い連鎖列を求める
vector<pii> getMaxLength() const;
// seq で与えられる操作をした際の次の状態にする
void move(const vector<pii>& seq);
// seq で与えられた操作をした際の状態から戻る
void undo(const vector<pii>& seq);
// 終わったかどうか
bool isCleared() const ;
bool operator<(const State& rhs) {return eval() < rhs.eval();}
//int dfs(int y, int x) const ;
};
vector<pii> State::getMaxLength() const {
return btk::getMaxLength(board);
}
// dp[i][j] = (i, j) 成分から動いて狭義単調減少列の最大長はいくつか
int dp[MAX][MAX];
int dfs(int y, int x, const State& state) {
int& ret = dp[y][x];
if (ret >= 0) return ret;
ret = 0;
if (state.board[y][x] == 0) return ret;
for (int i = 0; i < 4; i++) {
int ny = y+dy[i], nx = x+dx[i];
if (ny < 0 || ny >= state.height || nx < 0 || nx >= state.width) continue;
if (state.board[ny][nx] >= state.board[y][x]) continue;
ret = max(ret, dfs(ny, nx, state));
}
ret++;
return ret;
}
int State::eval() const {
// dp を求める
memset(dp, -1, sizeof(dp));
for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) {
dfs(i, j, *this);
}
int ret = 0;
for (int i = 0; i < height; i++) for (int j = 0; j < width; j++) {
ret += dp[i][j] * dp[i][j];
}
ret -= sum;
return ret;
}
void State::move(const vector<pii>& seq) {
int prev = -1;
for (pii p : seq) {
assert(0 <= p.first && p.first < height && 0 <= p.second && p.second < width);
assert(prev == -1 || prev == board[p.first][p.second]+1);
prev = board[p.first][p.second];
board[p.first][p.second]--;
}
sum -= seq.size();
}
void State::undo(const vector<pii>& seq) {
int prev = -1;
for (pii p : seq) {
assert(0 <= p.first && p.first < height && 0 <= p.second && p.second < width);
assert(prev == -1 || prev == board[p.first][p.second]+1);
prev = board[p.first][p.second];
board[p.first][p.second]++;
}
sum += seq.size();
}
bool State::isCleared() const {
return sum == 0;
}
int main() {
cin.tie(0);
ios::sync_with_stdio(false);
for (int i = 0; i < MAX; i++) for (int j = 0; j < MAX; j++) {
cin >> A[i][j];
}
State state(MAX, MAX);
for (int i = 0; i < MAX; i++) for (int j = 0; j < MAX; j++) {
state.board[i][j] = A[i][j];
state.sum += A[i][j];
}
vector<pii> ans;
while (!state.isCleared()) {
auto seq = state.getMaxLength();
for (auto p : seq) ans.push_back(p);
state.move(seq);
}
for (auto p : ans) {
cout << p.first+1 << " " << p.second+1 << endl;
}
return 0;
}
Submission Info
Submission Time |
|
Task |
A - 高橋君の山崩しゲーム |
User |
mayobutter |
Language |
C++14 (GCC 5.4.1) |
Score |
847160 |
Code Size |
7073 Byte |
Status |
AC |
Exec Time |
626 ms |
Memory |
1016 KB |
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 |
84677 / 100000 |
84964 / 100000 |
84756 / 100000 |
84317 / 100000 |
85044 / 100000 |
84374 / 100000 |
85345 / 100000 |
84379 / 100000 |
84638 / 100000 |
84666 / 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 |
580 ms |
1016 KB |
subtask_01_02.txt |
AC |
539 ms |
1016 KB |
subtask_01_03.txt |
AC |
585 ms |
1016 KB |
subtask_01_04.txt |
AC |
626 ms |
1016 KB |
subtask_01_05.txt |
AC |
587 ms |
1016 KB |
subtask_01_06.txt |
AC |
528 ms |
1016 KB |
subtask_01_07.txt |
AC |
526 ms |
1016 KB |
subtask_01_08.txt |
AC |
587 ms |
1016 KB |
subtask_01_09.txt |
AC |
570 ms |
1016 KB |
subtask_01_10.txt |
AC |
535 ms |
1016 KB |