SRM505 Div1Easy RectangleArea

http://community.topcoder.com/stat?c=problem_statement&pm=11400

ある長方形について頂点を含む4つの小長方形を考えると、このうち3つの面積がわかっている(Y)ならば残り1つの面積もわかる。これを繰り返すといずれ盤上の'Y'が増えなくなるため、小長方形の面積を質問する必要があり、その回数を調べる。
質問する小長方形はどれでもよさそうだが確証はない。

ケースが大きいとTLEするらしい。再帰部分が明らかに怪しいがいまいちわからない。改善中…
creepさんの記事などを参考にして通しました。TLE解では再帰時に頂点を全探索していたのでO(W^2H^2)だが、実際には'N'→'Y'としたところに関係する場所しか変わらないので、O(WH)に減らせるはず。結果として、全体ではO(W^3H^3)O(W^2H^2)に削減
creep06.hatenablog.com

改善後

#include <bits/stdc++.h>
using namespace std;

class RectangleArea {
public:
    int h,w;
    int board[51][51];
    int ret=0;
    // (sy,sx)を1頂点とした長方形について、穴埋め
    void greed(int sy,int sx){
        // 対角の座標で探索
        for(int y=0;y<h;y++){
            for(int x=0;x<w;x++){
                // 長方形でないので×
                if(sy==y||sx==x) continue;
                // 3つの小長方形の面積がわかっている
                if(board[sy][sx]+board[y][sx]+board[sy][x]+board[y][x]==3){
                    if(board[y][sx]==0){
                        board[y][sx]=1;
                        greed(y,sx);
                    }
                    if(board[sy][x]==0){
                        board[sy][x]=1;
                        greed(sy,x);
                    }
                    if(board[y][x]==0){
                        board[y][x]=1;
                        greed(y,x);
                    }
                }
            }
        }
    }
    
    int minimumQueries( vector <string> known ){
        h=known.size();
        w=known[0].size();
        for(int y=0;y<h;y++){
            for(int x=0;x<w;x++){
                if(known[y][x]=='Y') board[y][x]=1;
                else board[y][x]=0;
            }
        }
        // 面積がわかっているところを先に埋める
        for(int y=0;y<h;y++){
            for(int x=0;x<w;x++){
                if(board[y][x]==1){
                    greed(y,x);
                }
            }
        }
        // 質問しないといけないので実行する度に回数+1
        for(int y=0;y<h;y++){
            for(int x=0;x<w;x++){
                if(board[y][x]==0){
                    board[y][x]=1;
                    ret++;
                    greed(y,x);
                }
            }
        }
        return ret;
    }
};

改善前

#include <bits/stdc++.h>
using namespace std;

class RectangleArea {
public:
    int h,w;
    int board[51][51];
    int ret=-1;

    void greed(){
        for(int y=0;y<h-1;y++){
            for(int x=0;x<w-1;x++){
                for(int dy=y;dy<h;dy++){
                    for(int dx=x;dx<w;dx++){
                        if(board[y][x]+board[y][dx]+board[dy][x]+board[dy][dx]==3){
                            board[y][x]=board[y][dx]=board[dy][x]=board[dy][dx]=1;
                            greed();
                        }
                    }
                }
            }
        }
    }

    int minimumQueries( vector <string> known ){
        h=known.size();
        w=known[0].size();
        for(int y=0;y<h;y++){
            for(int x=0;x<w;x++){
                if(known[y][x]=='Y') board[y][x]=1;
                else board[y][x]=0;
            }
        }

        while(1){
            ret++;
            greed();
            bool end=true;
            for(int y=0;y<h;y++){
                for(int x=0;x<w;x++){
                    if(board[y][x]==0){
                        board[y][x]=1;
                        end=false;
                        break;
                    }
                }
                if(!end) break;
            }
            if(end) break;
        }
        return ret;
    }
};