ラベル カバー の投稿を表示しています。 すべての投稿を表示
ラベル カバー の投稿を表示しています。 すべての投稿を表示

SRM 623 DIV1 Easy - UniformBoard (○)

SRM 623 DIV1 Easy - UniformBoard (○)

問題


http://community.topcoder.com/stat?c=problem_statement&pm=13209&rd=15856

・N×Nのボードが与えられる。
・ボードの各セルには空白、apple,pearいずれかが置かれている。
・また、1回の操作でappleかpearを空白に移すことができる。
・最大の操作回数はKで、任意の長方形の中のセルがすべてappleであるようなときの
 最大の長方形の面積を求める。

解き方


・すべての長方形で検索すればよさそう。
・長方形を作ったとき、そもそも全体のappleより大きいセルは作れないので
 最初にすべてのappleの数を調べる必要がある。
・長方形を作ったときにpearが含まれているとき、空白が一つもないと移せないので
 最初に空白があるかどうかを調べる必要がある。
・空白は1回の操作でappleを置くことができるが、pearは一回どかしてからappleを置く必要が
 あるので2回の操作が必要。

・よって任意の長方形を考えた時、セルの数が全体のapple以下かつ、
 pearもしくは空白が含まれていないか、空白の数+pearの数×2<=Kかつ空白が全体に
 存在するときはその長方形をすべてappleにできる。

→System Passed.

コード


using namespace std;

#define all(c) (c).begin(),(c).end()
#define FORE(i,d,e) for(int i=d;i<e;i++)
#define FOR(i,s,e) for (int i = int(s); i != int(e); i++)
#define FORIT(i,c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ISEQ(c) (c).begin(), (c).end()

class UniformBoard {

public: int getBoard(vector<string> board, int K) {
int n=board.size();

int a=0,b=0;
FORE(i,0,n)FORE(j,0,n){
if(board[i][j]=='A')a++;
if(board[i][j]=='.')b=1;
}

int ret=0;
FORE(i,0,n)FORE(j,0,n)FORE(k,i,n)FORE(l,j,n){
int cnt=(k-i+1)*(l-j+1);
if(cnt>a)continue;
int curb=0,curp=0;
FORE(x,i,k+1)FORE(y,j,l+1){
if(board[x][y]=='P')curp++;
if(board[x][y]=='.')curb++;
}
if((curb==0&&curp==0) ||(curb+curp*2<=K && b))ret=max(ret,cnt);
}

return ret;
}

};

SRM 629 DIV1 Easy - RectangleCovering (×)

SRM 629 DIV1 Easy - RectangleCovering (×)

問題


http://community.topcoder.com/stat?c=problem_statement&pm=13344&rd=16060

長方形のホールがあり、縦と横の長さがわかっている。
また複数の長方形のボードが与えられ、それぞれのボードの縦と横の長さもわかっている。
ホールを覆うように複数のボードをつなげるとき、必要な最小のボードの数を求める。
ただし、ボードは重ねるようにしてつなげてもよいが、ホールにボードの角が覆われないようにする。


解き方


・普通に考えるとかなりの場合の数がありそう。
・なにか制約がないか例をあげてみる。
・あるボードが使えるかどうかは、そのうち小さい1辺がボードのどちらか1辺よりも大きくないといけない。
・これで使えるボードが選別できそう。

・ただ、それでも色々なつなげ方がありそう。
・角が覆われないようにする条件を満たすためには、ボードは縦一列、横一列のどちらかしか並べられない。
・これであとは上記を満たす長さのうち降順に並べればよさそう。

・System Failed

・ホールについて、縦に並べるか横に並べるか、両方の場合の検討が必要だった
・さらにボードについて、例外条件を見落としていた。
 ボードの縦横両方が1辺よりも大きければ大きい方を取る。
 そうでないとき、小さい方の辺が1辺より小さければ大きい方ととる。
 そのうえでつなげる方の辺以上の長さになればよい。

・System Passed

コード


using namespace std;

#define all(c) (c).begin(),(c).end()
#define FORE(i,d,e) for(int i=d;i<e;i++)
#define FOR(i,s,e) for (int i = int(s); i != int(e); i++)
#define FORIT(i,c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ISEQ(c) (c).begin(), (c).end()

class RectangleCovering {

public:

int minimumNumber(int holeH, int holeW, vector<int> boardH, vector<int> boardW) {
int ret=1e+9;

FORE(x,0,2){
vector<int> vx;
FORE(i,0,boardH.size()){
int minx=min(boardH[i],boardW[i]);
int maxx=max(boardH[i],boardW[i]);

if(maxx<=holeW)continue;
if(minx>holeW)vx.push_back(maxx);
else vx.push_back(minx);
}
sort(vx.rbegin(),vx.rend());

int score=0;
FORE(i,0,vx.size()){
score+=vx[i];
if(score>=holeH)ret=min(ret,i+1);
}
swap(holeH,holeW);
}

return ret==1e+9 ? -1 : ret;
}

};

SRM 614 DIV1 Easy - MinimumSquare

SRM 614 DIV1 Easy - MinimumSquare

問題


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

座標上に複数の点が与えられる。
座標上に正方形を描き、その正方形の中に少なくともK個以上与えられた点が入っているようににしたい。

このとき、描くことのできる最小の正方形の面積を求める。

解き方


点の数は100個なので、単純にすべての点の選び方を全探索しようとすると100C50で間に合わないので違う方法を考える。

今回x座標は100個、y座標は100個とするとすべての始点の選び方は10^4となる。
また、その選んだ始点に対してすべての座標を加えた場合の長さを調べ、
K個以上となったときにその中のK個目の長さが最小の長さであるので、毎回その長さの正方形の面積と比較して答えを更新する。

これで計算量は10^6となり間に合う。
始点の選び方は与えられた座標ではなく、x、y座標それぞれの点に対して行うのがポイント。

コード


using namespace std;

#define all(c) (c).begin(),(c).end()
#define FORE(i,d,e) for(int i=d;i<e;i++)
#define FOR(i,s,e) for (int i = int(s); i != int(e); i++)
#define FORIT(i,c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ISEQ(c) (c).begin(), (c).end()

class MinimumSquare {

public: long long minArea(vector<int> x, vector<int> y, int K) {
long long ret=9.2e+18;
int n=x.size();
int tmplen[n];
memset(tmplen,0,sizeof(tmplen));

FORE(i,0,n){
FORE(j,0,n){
int cnt=0;
FORE(k,0,n){
if(x[k]>=x[i]&&y[k]>=y[j]){
tmplen[cnt++]=max(x[k]-x[i],y[k]-y[j]);
}
}
if(cnt>=K){
sort(tmplen,tmplen+cnt);
long long len=tmplen[K-1]+2;
ret=min(ret,len*len);
}
}
}

return ret;
}

};

SRM 530 DIV1 Easy - GogoXCake

SRM 530 DIV1 Easy - GogoXCake

問題


http://community.topcoder.com/stat?c=problem_statement&pm=11274&rd=14723

ケーキをカットする問題。
カットされたあとのケーキの形と、カットするナイフが与えられる。
ナイフを当てるときは必ず、そのマスにもケーキがなければいけない。
カット後のケーキの形にすることができればYes,ダメならNoを返す。

解き方


単純にシミュレーションするだけ。

カットできるときはカットしなければ答えを導けないことがわかれば、単純に実装できる。

最初にカットするべきマスとダメなマスをマーキング。
次に順番にナイフを当てていき、全てカットすることができるときだけカットする。
最後にカットするべきマスが残っていればNo,残っていなければYes.

コード


class GogoXCake {

public: string solve(vector<string> cake, vector<string> cutter) {
int h=cake.size(),w=cake[0].size();
int ch=cutter.size(),cw=cutter[0].size();
int g[h][w];

FORE(i,0,h)FORE(j,0,w){
if(cake[i][j]=='.')g[i][j]=-1;
else g[i][j]=1;
}

FORE(i,0,h-ch+1){
FORE(j,0,w-cw+1){
int invalid=0;
FORE(a,i,ch+i)FORE(b,j,cw+j)if(cutter[a-i][b-j]=='.'&&g[a][b]!=-1)invalid=1;
if(invalid)continue;
FORE(a,i,ch+i)FORE(b,j,cw+j)if(cutter[a-i][b-j]=='.')g[a][b]=1;
}
}

FORE(i,0,h)FORE(j,0,w)if(g[i][j]==-1)return "NO";
return "YES";
}

};