http://poj.org/problem?id=1038
Time Limit: 15000MS | Memory Limit: 30000K | |
Total Submissions: 8917 | Accepted: 3404 | |
Case Time Limit: 5000MS |
Description
Input
Output
Sample Input
2 6 6 5 1 4 4 6 2 2 3 6 6 4 6 5 4 3 3 6 1 6 2 6 4
Sample Output
3 4
Source
由于M<=10所以可以状压。三进制状态压缩,2表示这个点不能放,1表示这个点能放但它的上一个点不能放,0表示这个点能放且它的上一个点也能放。用这一行的状态推出后一行的状态,首先对于不放矩形的状态,如果这一行为2那么对应的下一行就是1,如果这一行为1那么对应的下一行为0,如果这一行为0那么下一行也为0。然后由下一行不放的状态推该行放矩形的状态,如果连续两个0与上一行对应的位置也是0,那么可以竖着放一个矩形,如果连续3个0,那么可以横着放矩形。由于存在坏点,我们还要判断矩形里是否有坏点。我们可以搜索出所有放矩形的状态进行更新。复杂度O(n*m*3^m)。在状压dp转移的时候,用dfs搜索有效状态进行更新也是一种不错的优化手段。代码如下:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h> #include<math.h> #define nn 110000 #define inff 0x3fffffff typedef long long LL; using namespace std; int n,m,k; bool huai[200][20]; bool hu[200][20][200][20]; int dp[2][60000]; int po[20]; int w1[20],w2[20]; int ans,t; void fuck(int x) { for(int i=0;i<m;i++) { printf("%d",x%3); x/=3; } puts(""); } bool check(int x1,int y1,int x2,int y2) { int i,j,g,e; for(i=x1;i<=x2;i++) { for(j=y1;j<=y2;j++) { if(huai[i][j]) return true; } } return false; } void init() { int i,j,g,e; po[0]=1; for(i=1;i<=m;i++) po[i]=po[i-1]*3; memset(hu,false,sizeof(hu)); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { for(g=i;g<=n;g++) { for(e=j;e<=m;e++) { hu[i][j][g][e]=check(i,j,g,e); } } } } for(i=0;i<=1;i++) { for(j=0;j<po[m];j++) dp[i][j]=-1; } dp[0][po[m]-1]=0; } void dfs(int id,int zt,int fc,int h) { if(id==m) return ; int ix; if(id<m-1&&w2[id]==0&&w2[id+1]==0) { if(w1[id]==0&&w1[id+1]==0) { if(!hu[h-1][id+1][h+1][id+2]) { ix=zt+2*po[id]+2*po[id+1]; dp[1-t][ix]=max(dp[1-t][ix],fc+1); dfs(id+2,ix,fc+1,h); } } if(id<m-2&&w2[id+2]==0) { if(!hu[h][id+1][h+1][id+3]) { ix=zt+2*po[id]+2*po[id+1]+2*po[id+2]; dp[1-t][ix]=max(dp[1-t][ix],fc+1); dfs(id+3,ix,fc+1,h); } } } dfs(id+1,zt,fc,h); } void solve() { int i,j,g,e; int ix,tem,fc; t=0; for(i=0;i<n;i++) { for(j=0;j<po[m];j++) { if(dp[t][j]<0) continue; ix=j,tem=0; for(g=0;g<m;g++) { w1[g]=ix%3; ix/=3; if(w1[g]==0) w2[g]=0; else w2[g]=w1[g]-1; tem+=w2[g]*po[g]; } dp[1-t][tem]=max(dp[1-t][tem],dp[t][j]); dfs(0,tem,dp[t][j],i); } memset(dp[t],-1,sizeof(t)); t=1-t; } ans=0; for(i=0;i<po[m];i++) { ans=max(ans,dp[t][i]); } } int main() { int d,i; scanf("%d",&d); while(d--) { scanf("%d%d%d",&n,&m,&k); int u,v; memset(huai,false,sizeof(huai)); for(i=1;i<=k;i++) { scanf("%d%d",&u,&v); huai[u][v]=true; } init(); solve(); printf("%d\n",ans); } return 0; }