結果
| 問題 |
No.459 C-VS for yukicoder
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2016-11-20 13:19:06 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 18 ms / 2,000 ms |
| コード長 | 3,424 bytes |
| コンパイル時間 | 1,849 ms |
| コンパイル使用メモリ | 173,848 KB |
| 実行使用メモリ | 5,632 KB |
| 最終ジャッジ日時 | 2024-11-28 19:51:16 |
| 合計ジャッジ時間 | 5,152 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 58 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
int main(){
int x,y;
int width, height;
int n;
cin >> height >> width >> n;
cin.ignore();
// assert
assert(0 <= height && height <= 10000);
assert(0 <= width && width <= 10000);
assert(height * width <= 30000);
assert(0 <= n && n <= 30000);
assert(n <= height * width);
// X座標にブロックがいくつ積まれているか、を記録する。
// stringを保持する必要はない。
vector<int> field(width,0);
for (y = 0; y < height; y++){
string s;
cin >> s;
bool check_block = false;
for (x = 0; x < width; x++){
field[x] += s[x]=='#';
check_block |= s[x]=='#';
}
assert(check_block);
}
// 標準入力から与えられるコマンド。
vector<int> commands; // commands[i] : i番目のコマンド
vector<vector<int>> commands_bucket(width-2); // bucket[x]={e0,e1,..} : x座標にe_i番目のコマンドが与えられた
for (int i=0; i < n; i++){
int c;
cin >> c;
assert(0 <= c && c <= width - 3); // assert: 範囲外のコマンド
commands_bucket[c].push_back(commands.size());
commands.push_back(c);
}
// 最終的に出力するpack
vector<vector<int>> result_pack(n,vector<int>(3,0));
// 制約「全てのパックは1つ以上のブロックを必ず持つ」を満たすために、
// パックごと1つだけブロックを割り当てる。
// 左端列のブロックは、左端のパックのみがそこに設置できるはず。
// よって貪欲に左端のブロックから配置していくことができる。
int cursor = 0;
for (x = 0; x < width-2; x++){
cursor = max(cursor,x);
for (int cmdidx : commands_bucket[x]){
while (field[cursor] == 0) cursor++;
assert(cursor <= x+2); // assert: カーソルがコマンドより右にある。すなわち、ブロックが足りない。
result_pack[cmdidx][cursor-x]++;
field[cursor]--;
}
}
// 一般にブロックはまだ残っているはずなので、
// 残りのブロックを割り当てる。
// 上と同様に、左端のブロックからパックに配置していく。
for (x = 0; x < width-2; x++){
for (int cmdidx : commands_bucket[x]){
for (int i=0; i < 3; i++){
int fil = min(3-result_pack[cmdidx][i],field[x+i]); // x+i座標から取り出すブロックの数
assert(0<=fil && fil<=3); // assert: ブロックの取り出し方に不正
result_pack[cmdidx][i] += fil;
field[x+i] -= fil;
assert(0<=field[x+i] && result_pack[cmdidx][i]<=3); // ブロックが足りない、あるいはパックのブロック保有数に異常
}
}
}
// 出力するだけ
for (int i=0; i < n; i++){
for (y = 3; 0 < y; y--){
for (x = 0; x < 3; x++){
if (y<=result_pack[i][x]){
putchar('#');
}else{
putchar('.');
}
}
putchar('\n');
}
}
return 0;
}