SRM474 Div2 Hard(1000) SquaresCovering
動的計画法。2nの配列にビットが立っている点を覆う最小コストを格納。頂点を2つ選べば正方形の置き方が決まる。正方形を置く順番は任意なので、1つは最左の点を選ぶ。
#include <vector> using namespace std; class SquaresCovering { int countbit( int n ); public: int minCost( vector <int> x, vector <int> y, vector <int> cost, vector <int> sides ); }; int SquaresCovering::minCost( vector <int> x, vector <int> y, vector <int> cost, vector <int> sides ) { int n = (int)x.size(); int sn = (int)cost.size(); int INF = n*cost[0]; vector<int> C( 1<<n, INF ); C[0] = 0; for ( int bit=0; bit<n; bit++ ) { for ( int c=0; c<1<<n; c++ ) if ( countbit(c) == bit && C[c] < INF ) { int p1 = -1; for ( int i=0; i<n; i++ ) if ( ( c & 1<<i ) == 0 ) if ( p1 == -1 || x[i] < x[p1] || x[i] == x[p1] && y[i] < y[p1] ) p1 = i; for ( int p2=0; p2<n; p2++ ) if ( ( c & 1<<p2 ) == 0 && y[p2] <= y[p1] ) { for ( int s=0; s<sn; s++ ) { int t = c; for ( int i=0; i<n; i++ ) if ( ( c & 1<<i ) == 0 && x[p1] <= x[i] && x[i] <= x[p1]+sides[s] && y[p2] <= y[i] && y[i] <= y[p2]+sides[s] ) t |= 1<<i; C[t] = min( C[t], C[c]+cost[s] ); } } } } return C[(1<<n)-1]; } int SquaresCovering::countbit( int n ) { n = ( n & 0x55555555 ) + ( n >> 1 & 0x55555555 ); n = ( n & 0x33333333 ) + ( n >> 2 & 0x33333333 ); n = ( n & 0x0f0f0f0f ) + ( n >> 4 & 0x0f0f0f0f ); n = ( n & 0x00ff00ff ) + ( n >> 8 & 0x00ff00ff ); n = ( n & 0x0000ffff ) + ( n >>16 & 0x0000ffff ); return n; }