思路
- 由于时间取值空间较小,因此考虑在时间的维度上进行状态压缩
- 由于仅有联合屏障影响连续的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];
}
};
|