質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
デバッグ

デバッグはプログラムのバグや欠陥を検知し、開発中のバグを取り除く為のプロセスを指します。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

3316閲覧

【競技プログラミング】全てのマス目を一度だけ通る単一の閉曲線

musharna000

総合スコア18

デバッグ

デバッグはプログラムのバグや欠陥を検知し、開発中のバグを取り除く為のプロセスを指します。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2015/06/20 03:17

AOJ 0236 Alien Messagesを解いていて詰まってしまったのでアドバイス頂きたいです。

0(通れる),1(通れない)でマップが与えられて、
そのマップに全ての0のマス目を一度だけ通る単一の閉曲線が描けるかどうかを判定する
という問題に対して、DFSで閉曲線がかけるかどうか判定するプログラムを書き、
ナイーブな実装だとTLEなので以下の条件で枝刈りをすることにしました。
(space_sumは0のマスの個数を表します)
・space_sumが4より少なかったらそもそも閉曲線がかけない
・space_sumが偶数でなければそもそも閉曲線がかけない
・DFSで今見ているマス(1にしてある)に隣接するマスおよびスタートのマスに隣接するマス以外で隣接するまだ見ていない(1にされていない)マスの個数が1のマスが存在したら突き当たりになるので閉曲線がかけない。

これで制限時間以内には通りましたが、WAになってしまいました。
そもそも上記の条件が間違っているのでしょうか、それとも実装にミスがあるのでしょうか。
コードを何度も確認してみたのですがどこが間違っているのか私にはわかりませんでした。
お判りの方おられましたら、コメント頂ければ幸いです。
宜しくお願い致します。

lang

1#include <iostream> 2#include <stdio.h> 3#include <sstream> 4#include <string> 5#include <vector> 6#include <map> 7#include <queue> 8#include <algorithm> 9#include <set> 10#include <math.h> 11#include <utility> 12#include <stack> 13#include <string.h> 14#include <complex> 15using namespace std; 16const int INF = 1<<29; 17const double EPS = 1e-8; 18typedef vector<int> vec; 19typedef vector<vec> mat; 20typedef pair<int,int> P; 21struct edge{int to,cost;}; 22 23const int dx[] = {0,0,1,-1}; 24const int dy[] = {1,-1,0,0}; 25 26int field[7][7]; 27int space_sum; 28int W, H; 29int sy, sx; 30 31int get_dim(int y, int x){ 32 int dim = 0; 33 for(int k=0;k<4;k++){ 34 int nx = x + dx[k], ny = y + dy[k]; 35 if(nx<0||W<=nx||ny<0||H<=ny)continue; 36 if(field[ny][nx]==0) dim++; 37 } 38 return dim; 39} 40 41bool dfs(int y, int x, int d_sum){ 42 if(d_sum==space_sum){ 43 if(abs(sy-y)+abs(sx-x)==1)return true; 44 }else{ 45 for(int i=0;i<H;i++){ 46 for(int j=0;j<W;j++){ 47 if(field[i][j]) continue; 48 if(abs(sy-i)+abs(sx-j)==1||abs(y-i)+abs(x-j)==1) continue; 49 if(get_dim(i, j)==1) return false; 50 } 51 } 52 for(int i=0;i<4;i++){ 53 int nx = x + dx[i], ny = y + dy[i]; 54 if(nx<0||W<=nx||ny<0||H<=ny)continue; 55 if(field[ny][nx]==0){ 56 field[ny][nx] = 1; 57 if (dfs(ny, nx, d_sum+1)) return true; 58 field[ny][nx] = 0; 59 } 60 } 61 } 62 return false; 63} 64 65int main(){ 66 while(cin >> W >> H, W){ 67 space_sum = 0; 68 sy = -1; sx = -1; 69 for(int i=0;i<H;i++){ 70 for(int j=0;j<W;j++){ 71 scanf("%d",&field[i][j]); 72 space_sum += !field[i][j]; 73 if(sy<0&&!field[i][j]){ 74 sy = i; sx = j; 75 } 76 } 77 } 78 field[sy][sx] = 1; 79 if(space_sum<4||space_sum%2==1||!dfs(sy, sx, 1)){ 80 cout << "NO" << endl; 81 continue; 82 }else{ 83 cout << "YES" << endl; 84 } 85 } 86 87 return 0; 88} 89

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

全てのマスに石像が配置されている場合にマズいことになりそうな気がします。

投稿2015/06/21 02:39

IchigoTaruto

総合スコア159

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

musharna000

2015/06/21 05:17

コメントありがとうございます。 確かにfield[-1][-1]となるのでマズいですね。 if(sy>=0) field[sy][sx] = 1;に修正してサブミットしてみたのですが、まだWAでした。 もっと他の場所が間違っているみたいです。申し訳ありません。
takotakot

2015/06/21 09:50

sy == -1 のときに NO を返すようにはしてありますか?
IchigoTaruto

2015/06/21 09:52

sy == -1 のときは space_sum<4 の条件に引っかかるので NO になると思います。
guest

0

!0 は 1 なのでしょうか
ちょっと調べたところ 1, 非0 両方見受けられたので確証はないのですが、仮に 非0 だとすると

lang

1space_sum += !field[i][j];

の部分はマズい気がします。

投稿2015/06/21 09:51

IchigoTaruto

総合スコア159

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takotakot

2015/06/21 10:00

気付かなかったですね…入力は 0/1 なので space_sum += (1 | field[i][j]); が良さそうでしょうか。
takotakot

2015/06/21 10:02

間違えました。XOR なので ^ ですね。
musharna000

2015/06/21 10:39

確かに環境によっては非0になるかもしれないのでこの書き方は良くないですね。 気をつけようと思います。ご指摘ありがとうございました!
guest

0

ベストアンサー

大枠が間違っているようには思えませんでした。サンプルも通りますね。
W = H = 1 のときはどういう扱いでしょうか?閉曲線が書ける気がします。

だから、
0. 1マスだけが空いている
0. 2マスが連続して空いている
場合は特別扱いする必要があるかもしれませんね。

「入力データセットごとに、Yes または No を出力します。」
なので
YES や NO ではなく、Yes と No です。

投稿2015/06/21 00:36

編集2015/06/21 10:04
takotakot

総合スコア1111

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

musharna000

2015/06/21 05:11

コメントありがとうございます。 1マスだけが空いているとき、2マスが連続して空いているときについて 例外的にYESを出力するようにしてサブミットしてみましたがWAでした。 上記のような場合は全ての0マスを一度だけ通る閉曲線とは言えないように思います。
takotakot

2015/06/21 10:04

致命的なミスを見つけましたので、追記しました。
musharna000

2015/06/21 10:37

>YES や NO ではなく、Yes と No です。 ご指摘の通りでした。修正したところACされました。 こんな初歩的なミスでお手を煩わせてしまって申し訳ないです。 ご協力ありがとうございました!
guest

0

get_dimの引数のxとy,それとその中のif(field[ny][nx]==0)で使っているnxとnyがそれぞれ逆ではないでしょうか?

投稿2015/06/20 04:59

swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

musharna000

2015/06/20 05:14

0<=y座標<H, 0<=x座標<Wでget_dim(y座標, x座標)でfield[y座標][x座標]としてつかっているので大丈夫だと思います。get_dim内のnx,nyの書く順番が逆になっているので紛らわしかったですね。すみません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問