图很小,考虑状压dp。每一个位置只与前面一个位置的dp值有关,因此可以使用滚动数组优化空间。因为每一个方块的放置最多影响到下一行往右两个的位置,所以mask大概可以开到25位,空间是比较吃紧的,所以使用哈希表进行存储达到空间上的优化。
状压dp一向是挺难写的,对代码能力要求较高,具体见代码吧。。
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define ll long long
#define pq priority_queue
#define mp make_pair
#define pii pair<int,int>
#define mod 111911
#define debug(x) cerr<<#x<<"="<<x<<'\n'
const int INF=1000;
int lowbit(int x) {return x&(-x);}
int n,m,cnt=0;
struct F{
int tot,ans;
int head[mod];
vector <int> val,dp,nxt;
void init() {
tot=0;
ans=1e9+11;
val.clear();
dp.clear();
nxt.clear();
memset(head,-1,sizeof(head));
}
void update(int mask,int key) {
ans=min(ans,key);
int cur=mask%mod;
for (int i=head[cur];i!=-1;i=nxt[i]) {
if (val[i]==mask) {
dp[i]=min(key,dp[i]);
return;
}
}
nxt.pb(head[cur]);
dp.pb(key);
val.pb(mask);
head[cur]=tot++;
return;
}
}f[2];
//1<<25
class BrickPuzzle{
public:
int leastShapes(vector<string> board) {
n=board.size(),m=board[0].size();
int cur=0,lst=1;
f[cur].init();f[lst].init();
f[cur].update(0,0);
int ans=1e9+11;
for (int i=0;i<n;i++)
for (int j=0;j<m;j++) {
swap(cur,lst);
f[cur].init();
for (int k=0;k<f[lst].tot;k++) {
int mask=f[lst].val[k];
if (mask&1) {
f[cur].update(mask>>1,f[lst].dp[k]);
continue;
}
if (board[i][j]=='X') {
f[cur].update(mask>>1,f[lst].dp[k]);
}
if (i+1<n&&j+1<m&&!((mask>>1)&1)&&!((mask>>(m+1))&1)&&!((mask>>m)&1)) {
int nmask=mask>>1;
nmask|=1;
nmask=nmask|(1<<(m-1));
nmask=nmask|(1<<m);
f[cur].update(nmask,f[lst].dp[k]+1);
}
if (j+3<m&&!((mask>>1)&1)&&!((mask>>2)&1)&&!((mask>>3)&1)) {
int nmask=mask>>1;
nmask|=1;
nmask|=2;
nmask|=4;
f[cur].update(nmask,f[lst].dp[k]+1);
}
if (i+1<n&&j+2<m&&!((mask>>1)&1)&&!((mask>>(m+1))&1)&&!((mask>>(m+2))&1)) {
int nmask=mask>>1;
nmask|=1;
nmask|=(1<<m);
nmask|=(1<<m+1);
f[cur].update(nmask,f[lst].dp[k]+1);
}
if (i+1<n&&j>0&&j+1<m&&!((mask>>1)&1)&&!((mask>>m-1)&1)&&!((mask>>m)&1)) {
int nmask=mask>>1;
nmask|=1;
nmask|=(1<<m-1);
nmask|=(1<<m-2);
f[cur].update(nmask,f[lst].dp[k]+1);
}
}
}
if (f[cur].ans==1e9+11) return -1;
return f[cur].ans;
}
};