西电oj 1038 状压dp
西电oj 1038 状压dp
1038: 裁玻璃
时间限制: 1 Sec 内存限制: 128 MB提交: 33 解决: 4
[提交][状态][讨论版]
题目描述
张老板的玻璃店开张了,生意火爆。今天,隔壁玻璃店的刘老板拿来一块玻璃,意在***难张老板。刘老板说:“我这块玻璃是由N(行)*M(列)小正方形玻璃拼成的,但是其中有一些玻璃坏了,我希望你现在把它裁成尽量多的2*2的小玻璃,而且这些小玻璃都不能有坏的地方。如果你裁出来的块数不是最多的,我就把你赶出建材市场。”
现在,张老板来拜托你帮他解决这个问题,聪明的你可以告诉张老板,最多能裁出多少块2*2的小玻璃吗?
输入
有多组输入数据,第一行为一个数字T,代表有T组输入数据 (0<T<=30)。
接下来为T组数据,每组数据的第一行为两个正整数N和M(1<=N<=10,1<=M<=10),表示玻璃的大小,接下来的N行、每行M个数字(0或1)表示玻璃中每个位置的状态,0表示这个位置是坏的,1表示这个位置是好的。
输出
一共T行。
对于每组数据,输出一个整数,表示最多的2*2小玻璃块数。
样例输入
2
2 3
1 1 1
1 1 1
4 4
0 0 1 1
0 1 1 1
1 1 1 1
1 1 1 1
样例输出
1 3
思路:和poj1185一样,状压dp,dp(i,j)=max(dp(i,j),dp(i-1,k)+sum[j])(状态j,k存在合法且不冲突)
dp表示第i行的状态为j时的玻璃数,按行进行递推,sum[j]表示状态为j时这一行的玻璃数。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const int maxn=1100; const int INF=(1<<29); int N,M; int Map[maxn]; int dp[maxn][maxn]; int state[maxn],sum[maxn],cnt; void InitState() { memset(state,0,sizeof(state)); cnt=0; for(int i=0;i<(1<<(M-1));i++){ if((i&(i<<1))) continue; state[cnt++]=i; } } void InitSum() { memset(sum,0,sizeof(sum)); for(int i=0;i<cnt;i++){ for(int j=0;j<M-1;j++){ if(state[i]&(1<<j)) sum[i]++; } } } bool jud_map(int i,int row) { int s=state[i]; bool flag=1; for(int j=0;j<M-1;j++){ if(s&(1<<j)){ if(Map[row]&(1<<j)&&(Map[row]&(1<<(j+1)))&&(Map[row+1]&(1<<j))&&(Map[row+1]&(1<<(j+1)))) continue; else{ flag=0;break; } } } return flag; } bool jud(int a,int b) { int s=state[a],t=state[b]; if((s&t)||(s&(t<<1))||((s<<1)&t)) return 0; return 1; } int main() { int T;cin>>T; while(T--){ cin>>N>>M; memset(Map,0,sizeof(Map)); for(int i=1;i<=N;i++){ int t; for(int j=0;j<M;j++){ scanf("%d",&t); if(t) Map[i]|=(1<<j); } } InitState(); InitSum(); memset(dp,0,sizeof(dp)); for(int i=1;i<=N-1;i++){ for(int j=0;j<cnt;j++){ if(!jud_map(j,i)) continue; if(i==1){ dp[i][j]=max(dp[i][j],sum[j]); continue; } else{ for(int k=0;k<cnt;k++){ if((!jud_map(k,i-1))||(!jud(j,k))) continue; dp[i][j]=max(dp[i][j],dp[i-1][k]+sum[j]); } } } } int ans=0; for(int i=0;i<cnt;i++){ if(dp[N-1][i]>ans) ans=dp[N-1][i]; } cout<<ans<<endl; } return 0; }
没有AC不了的题,只有不努力的ACMER!