思路
由于时间取值空间较小 ,因此考虑在时间的维度上进行状态压缩 由于仅有联合屏障影响连续的2个结点 ,枚举每个点在每个时间所使用的联合屏障情况 (使用五位二进制压缩,第i位为1当且仅当在该时间点使用联合屏障 ) 转移的限制:
与前面一个结点使用的联合屏障互不相交 如果当前结点还有遭受撞击的时刻,只能单独开屏障
class Solution {
public :
int defendSpaceCity ( vector< int > & time, vector< int > & position) {
int max_time = 0 ;
int max_pos = 0 ;
for ( int i : time) { max_time = max ( max_time, i) ; }
for ( int i : position) { max_pos = max ( max_pos, i) ; }
vector< int > q[ 1 << max_time] ;
for ( int i = 0 ; i< ( 1 << max_time) ; i++ )
{
for ( int j = 0 ; j< ( 1 << max_time) ; j++ )
{
int u = 4 ;
bool flag = true ;
while ( u>= 0 )
{
if ( ( ( i >> u) & 1 ) == 1 && ( ( j >> u) & 1 ) == 1 )
{ flag = false ; break ; }
u-- ;
}
if ( flag) q[ i] . push_back ( j) ;
}
}
int s[ 1 << max_time] ;
int p[ 1 << max_time] ;
for ( int i = 0 ; i< 1 << max_time; i++ )
{
int k = 0 ;
int u = 0 ;
while ( u <= max_time - 1 && ( ( i >> u) & 1 ) == 0 ) u++ ;
bool flag = true ;
while ( u<= max_time - 1 )
{
if ( flag) k+= 2 ; else k++ ;
u++ ;
while ( u <= max_time - 1 && ( ( i >> u) & 1 ) == 1 ) k++ , u++ ;
int num_zero = 0 ;
while ( u <= max_time - 1 && ( ( i >> u) & 1 ) == 0 ) num_zero++ , u++ ;
if ( u<= max_time - 1 )
{
if ( num_zero <= 1 ) k+= num_zero, flag = false ;
else flag = true ;
}
}
s[ i] = k;
k= 0 , u= 0 , flag = true ;
while ( u <= max_time - 1 && ( ( i >> u) & 1 ) == 0 ) u++ ;
while ( u<= max_time - 1 )
{
if ( flag) k+= 3 ; else k++ ;
u++ ;
while ( u <= max_time - 1 && ( ( i >> u) & 1 ) == 1 ) k++ , u++ ;
int num_zero = 0 ;
while ( u <= max_time - 1 && ( ( i >> u) & 1 ) == 0 ) num_zero++ , u++ ;
if ( u<= max_time - 1 )
{
if ( num_zero <= 0 ) k+= num_zero, flag = false ;
else flag = true ;
}
}
p[ i] = k;
}
map< int , int > c;
for ( int i = 0 ; i< time. size ( ) ; i++ ) c[ position[ i] ] |= ( 1 << ( time[ i] - 1 ) ) ;
int dp[ max_pos + 1 ] [ 1 << max_time] ;
for ( int i = 0 ; i< max_pos + 1 ; i++ )
for ( int j = 0 ; j< 1 << max_time; j++ )
dp[ i] [ j] = INT_MAX;
for ( int j = 0 ; j< 1 << max_time; j++ )
{
dp[ 0 ] [ j] = s[ c[ 0 ] & ( ~ j) ] + p[ j] ;
}
for ( int i = 1 ; i< max_pos + 1 ; i++ )
{
for ( int j = 0 ; j< 1 << max_time; j++ )
{
for ( int k : q[ j] )
{
dp[ i] [ j] = min ( dp[ i- 1 ] [ k] + s[ c[ i] & ( ~ j) & ( ~ k) ] + p[ j] , dp[ i] [ j] ) ;
}
}
}
return dp[ max_pos] [ 0 ] ;
}
} ;