Submission #434739


Source Code Expand

#include <cassert>
#include <functional>
#include <set>
#include <ctime>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdio>
#ifndef ONLINE_JUDGE //POJ
# include <complex>
# include <random>
# include <array>
# define mkt make_tuple
# define empb emplace_back
#endif
#ifdef _LOCAL
# include "for_local.h"
#endif
using namespace std;
typedef unsigned int uint; typedef long long ll; typedef unsigned long long ull;
#define repi(_I, _B, _E) for(int _I = (_B); (_I) < (_E); ++ (_I))
#define rep(_I, _N) for(int _I = 0; (_I) < (_N); ++ (_I))
#define mkp make_pair
#define all(_X) (_X).begin(), (_X).end()
inline int scani() { int n; scanf("%d", &n); return n; }


static ll const MOD = 1000000007;
static int const INF = 1<<29;
using pii = pair<int,int>;

int n; //不定セルの数
vector<int> dp;

//[index]=k: 位置 index に数字 k が書かれている
array<int, 5 * 5> board;

//[k]=index
array<int, 5 * 5> boardInv;

//[l]=index: l 番目の不定セルの位置 (昇順)
array<int, 5 * 5> pos;

//[index]=s: 位置 index の不定セルに対応する一元集合
array<int, 5 * 5> bitFromIndex;

//不定数字列と番兵
vector<int> flexnums;

int popcount(int s) {
	int k = 0;
	rep(i, 32) {
		if ( s & (1 << i) ) ++k;
	}
	return k;
}

//状態 s で数字 k を書き込む直前に、(i,j) セルが書き込み済みか否か
bool written(int s, int k, int i, int j)
{
	return (
		//固定数字が書き込み済み
		board[i * 5 + j] < k
		//書き込み済みの不定セル
		|| (s & bitFromIndex[i * 5 + j])
	);
}

bool forbidden(int s, int k, int i, int j)
{
	//両隣のうち片方だけが埋まっていたらダメ
	//どちらかが枠外ならセーフ
	if ( 1 <= i && i + 1 < 5 ) {
		bool const up = written(s, k, i - 1, j);
		bool const lo = written(s, k, i + 1, j);
		if ( up ^ lo ) return true;
	}
	if ( 1 <= j && j + 1 < 5 ) {
		bool const lef = written(s, k, i, j - 1);
		bool const rig = written(s, k, i, j + 1);
		if ( lef ^ rig ) return true;
	}
	return false;
}

//状態 s において l 番目の不定セルに数字 k が書き込まれた場合を加算
void update(int s, int k, int l) {
	int const index = pos[l];

	if ( forbidden(s, k, index / 5, index % 5) ) {
		return;
	}

	int const t = s | (1 << l);
	dp[t] = (dp[t] + dp[s]) % MOD;
}

bool verify(int s, int pc) {
	int k = (pc == 0 ? 0 : flexnums[pc - 1] + 1);
	for ( ; k < flexnums[pc]; ++k ) {
		int const index = boardInv[k];
		if ( forbidden(s, k, index / 5, index % 5) ) {
			return false;
		}
	}
	return true;
}

int solve() {
	dp.resize(1 << n + 1, 0);
	dp[0] = 1;

	rep(s, 1 << n) {
		int const pc = popcount(s);

		//固定数字を順に書き込んでいく間に禁止状態を経由しないことを確認する
		if ( !verify(s, pc) ) continue;

		int const k = flexnums[pc]; //次に書く数字
		rep(l, n) {
			if ( s & (1 << l) ) continue; //配置済み
			update(s, k, l);
		}
	}
	return dp[(1 << n) - 1];
}

signed main() {
	fill(all(boardInv), INF);

	rep(i, 5 * 5) {
		int k;
		cin >> k; --k;
		board[i] = (k >= 0 ? k : INF);

		if ( k < 0 ) { //不定セル
			bitFromIndex[i] = 1 << n;
			pos[n] = i;
			++n;
		} else { //固定セル
			boardInv[k] = i;
		}
	}
	rep(k, 5 * 5) {
		if ( boardInv[k] == INF ) {
			flexnums.push_back(k);
		}
	}
	flexnums.push_back(5 * 5);

	cout << solve() << endl;
	return 0;
}

Submission Info

Submission Time
Task D - 25個の整数
User vain0
Language C++11 (GCC 4.9.2)
Score 100
Code Size 3627 Byte
Status AC
Exec Time 380 ms
Memory 8992 KB

Judge Result

Set Name Sample Subtask1 Subtask2
Score / Max Score 0 / 0 30 / 30 70 / 70
Status
AC × 4
AC × 19
AC × 29
Set Name Test Cases
Sample sample-01.txt, sample-02.txt, sample-03.txt, sample-04.txt
Subtask1 sample-01.txt, sample-02.txt, sample-03.txt, sample-04.txt, test-1-01.txt, test-1-02.txt, test-1-03.txt, test-1-04.txt, test-1-05.txt, test-1-06.txt, test-1-07.txt, test-1-08.txt, test-1-09.txt, test-1-10.txt, test-1-11.txt, test-1-12.txt, test-1-13.txt, test-1-14.txt, test-1-15.txt
Subtask2 sample-01.txt, sample-02.txt, sample-03.txt, sample-04.txt, test-1-01.txt, test-1-02.txt, test-1-03.txt, test-1-04.txt, test-1-05.txt, test-1-06.txt, test-1-07.txt, test-1-08.txt, test-1-09.txt, test-1-10.txt, test-1-11.txt, test-1-12.txt, test-1-13.txt, test-1-14.txt, test-1-15.txt, test-2-01.txt, test-2-02.txt, test-2-03.txt, test-2-04.txt, test-2-05.txt, test-2-06.txt, test-2-07.txt, test-2-08.txt, test-2-09.txt, test-2-10.txt
Case Name Status Exec Time Memory
sample-01.txt AC 26 ms 804 KB
sample-02.txt AC 23 ms 928 KB
sample-03.txt AC 23 ms 928 KB
sample-04.txt AC 25 ms 800 KB
test-1-01.txt AC 24 ms 924 KB
test-1-02.txt AC 22 ms 928 KB
test-1-03.txt AC 23 ms 796 KB
test-1-04.txt AC 24 ms 932 KB
test-1-05.txt AC 24 ms 924 KB
test-1-06.txt AC 23 ms 804 KB
test-1-07.txt AC 23 ms 924 KB
test-1-08.txt AC 23 ms 928 KB
test-1-09.txt AC 23 ms 924 KB
test-1-10.txt AC 24 ms 796 KB
test-1-11.txt AC 25 ms 800 KB
test-1-12.txt AC 26 ms 704 KB
test-1-13.txt AC 24 ms 804 KB
test-1-14.txt AC 24 ms 924 KB
test-1-15.txt AC 24 ms 676 KB
test-2-01.txt AC 32 ms 1180 KB
test-2-02.txt AC 25 ms 916 KB
test-2-03.txt AC 26 ms 920 KB
test-2-04.txt AC 41 ms 1308 KB
test-2-05.txt AC 61 ms 1756 KB
test-2-06.txt AC 350 ms 8984 KB
test-2-07.txt AC 380 ms 8988 KB
test-2-08.txt AC 360 ms 8992 KB
test-2-09.txt AC 346 ms 8920 KB
test-2-10.txt AC 373 ms 8984 KB