\ (Bugs POJ ~ 1038 ~ ~ ~ * ~ the Integrated Inc is an: \) (complex-shaped pressure DP)
\(solution:\)
A very tangled subject, wrote most of the day, wanted to practice your hand, the results of which Shousheng. In fact, according to that road before artillery positions it should not be written, but always feel that their ideas will be better, and a small amount of code.
The core idea of bloggers is actually a binary number to compress with three rows of the state, because the left to the right binary easily. Then there will be very bad if the ternary transfer.
We can use a binary number to the pre-compression section \ (I \) dysfunctions three rows down, the front \ (m \) bins Table \ (I \) lines, the intermediate \ (m \) th binary bitmap \ (i + 1 \) line, after \ (m \) bins table \ (i + 2 \) line
We set up a box left corner is represented by that point
We can use the search to the seizure of a rectangular placement programs in a row, this well written, the only line of code face a handwriting function is used to find this one. It is also shown to use a binary, three rows in this embodiment is a rectangular parallelepiped covered condition.
Then we need to step 3 in the one-line placement program to find the program up and down two rows of stitching program (in fact, is to use a binary compression scheme will come in two lines). Placing a single row enumeration direct violence program, then the binary operation to determine whether a conflict: the following
for(rg i=1;i<=tt;++i) for(rg j=1;j<=tt;++j) if(!((b[i]>>m)&b[j])){ r[++st]=j; p[i][j]=st; //r表示方案的下面一行用的那个单行方案 g[st]=(b[i]>>m)|b[j]; //找出两行的放置方案 }
Then we set up state must state the first two lines are included into it: Let \ (f [i] [j ] \) denotes \ (i \) line of the first two lines state \ (g [j] \) Significance in the above code
然后我们就可以开始常规转移,但是数组 \(r\) 和数组 \(p\) 一定要搞清楚!
\(code:\)
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define db double
#define rg register int
using namespace std;
int n,m,ff,tt,st,ans;
int a[155];
int b[305];
int c[305];
int g[3005];
int r[3005];
int p[305][305];
int f[155][3005];
inline void dfs(int i,int v,int vv){ //用一个二进制表示一行的状态(在某一行放,下面两行都有可能被覆盖,用一个二进制将这三行压在一起)
if(i==m){b[++tt]=v; c[tt]=vv; return ;} dfs(i+1,v,vv); //导入方案
if(i+3<=m)dfs(i+3,v|(7<<i)|(7<<(i+m)),vv+1); //放入横的长方体
if(i+2<=m)dfs(i+2,v|(3<<i)|(3<<(i+m)|(3<<(i+m+m))),vv+1); //放入竖的长方体
}
int main(){
rg t; cin>>t;
while(t--){
cin>>n>>m>>ff; ans=0; //读入
memset(a,0,sizeof(a));
memset(f,0,sizeof(f));
tt=0; st=0; dfs(0,0,0); //初始化
for(rg i=1;i<=tt;++i)
for(rg j=1;j<=tt;++j)
if(!((b[i]>>m)&b[j])){
r[++st]=j; p[i][j]=st; //r表示方案的下面一行用的那个单行方案
g[st]=(b[i]>>m)|b[j]; //找出两行的放置方案
}
for(rg i=1;i<=ff;++i){
rg x,y; cin>>x>>y;
a[x]|=1<<(y-1);
} a[n+1]=(1<<m)-1; //障碍的二进制读入,最后还要加一行障碍,防止长方体出界
for(rg i=1;i<=n;++i){
a[i]|=(a[i+1]<<m)|(a[i+2]<<(m+m)); //连续三行障碍压进一个二进制里
for(rg j=1;j<=st;++j)
for(rg k=1;k<=tt;++k)
if(!(((g[j]>>m)|a[i])&b[k])){ //这一行放的方案与前面的方案还有障碍不会冲突
f[i][p[r[j]][k]]=max(f[i][p[r[j]][k]],f[i-1][j]+c[k]);
ans=max(ans,f[i][p[r[j]][k]]); //因为多加了一行障碍,不用怕出界
}
} printf("%d\n",ans);
}
return 0;
}