PKU 1020 Anniversary Cake
バックトラック。余りが出ないようにという条件があるので、各深さでは最初に見つけたケーキの残りを切り取ればよい。
#include <iostream> #include <numeric> using namespace std; int s; // ケーキサイズ bool cake[99][99]; // ケーキ int piece[11]; // 添字の大きさのピースの個数 bool BT(); int main() { int t; cin >> t; while ( t-- > 0 ) { // 入力 int n; cin >> s >> n; for ( int i=1; i<=10; i++ ) piece[i] = 0; for ( int i=0; i<n; i++ ) { int a; cin >> a; piece[a]++; } // 探索 for ( int x=0; x<s; x++ ) for ( int y=0; y<s; y++ ) cake[x][y] = true; bool success = true; int sum = 0; for ( int i=1; i<=10; i++ ) sum += piece[i] * i*i; if ( sum != s*s ) success = false; if ( success ) success = BT(); cout << ( success ? "KHOOOOB!" : "HUTUTU!" ) << endl; } return 0; } bool BT() { // 全て切り取れたら終了 if ( accumulate( piece+1, piece+11, 0 ) == 0 ) return true; // ケーキが残っている場所を探す int x, y; for ( x=0; x<s; x++ ) for ( y=0; y<s; y++ ) if ( cake[x][y] ) goto found; found:; // 各サイズのピースを切り取って再帰 for ( int i=10; i>0; i-- ) if ( piece[i] > 0 && x + i <= s && y + i <= s ) { bool ok = true; for ( int xx=0; xx<i && ok; xx++ ) for ( int yy=0; yy<i && ok; yy++ ) if ( ! cake[x+xx][y+yy] ) ok = false; if ( ! ok ) continue; piece[i]--; for ( int xx=0; xx<i; xx++ ) for ( int yy=0; yy<i; yy++ ) cake[x+xx][y+yy] = false; bool f = BT(); piece[i]++; for ( int xx=0; xx<i; xx++ ) for ( int yy=0; yy<i; yy++ ) cake[x+xx][y+yy] = true; if ( f ) return true; } return false; }
コメントと改行を削って、GCC 444B。2009/12/13 現在最短。
s, // ケーキのサイズ c[64][64], // [0][0]:ピース数 // [1-10][0]:添字の大きさのピース数 // [1-][1-]:ケーキ f,j; B(x,y,i) { // ケーキが残っている場所を探す for(i=0;i<s*s&!c[x=i%s][y=i/s+1];i++); // 残りが無ければ終了 if(i>=s*s) return 1; for(i=10;i;++*c[i--]) { // サイズ i の大きさのピースが切り取れるか調べる for(j=i*i;~--j&&c[x+j%i][y+j/i];); // サイズ i のピースが残っていれば切り取る if(~--*c[i]&&!~j) { for(j=i*i;~--j;) c[x+j%i][y+j/i]=0; // 再帰 f=B(); for(j=i*i;~--j;) c[x+j%i][y+j/i]=1; // 残りのピースも切り取れればOK if(f) return 1; } } return 0; } main(t) { for(scanf("%d",&t);t--;puts(f==s*s&&B()?"KHOOOOB!":"HUTUTU!")) { // 初期化 memset(c,0,16384);f=0; // 読み込み・ピースの合計サイズを計算 for(scanf("%d%d",&s,*c);~--**c;f+=j*j) scanf("%d",&j), ++*c[j]; // ケーキの初期化 for(j=s*s;~--j;) c[j%s][j/s+1]=1; } }