本来是看这个题是课件上推荐的题当中AC率最高的,结果还看了两天才看明白T^T,三进制状态压缩,什么鬼东西,一个DP居然还要100行代码,太不像话了==
参考博客:http://www.cnblogs.com/vongang/archive/2012/07/30/2615322.html http://www.cnblogs.com/yefeng1627/archive/2013/01/15/2861786.html
代码是前者的,照着背了一遍,主体的思想还是用三进制表达当前状态然后由递归的方法寻找最优解,而且还用了滚动数组两只来表示当前行和前一行的状态。核心是选择2x3和3x2的情况,两行三列为什么只判断一个就行了呢,因为滚动数组的状态是表示当前状态是上一行状态的,所以判断当前行的值就可以。具体看代码
/***********
poj1038
2016.1.5
632K 1016MS C++ 2427B
别人的代码
***********/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define Max(a,b) (a>b?a:b)
#define N 59050
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define Max(a,b) (a>b?a:b)
#define N 59050
//三进制
int tri[12]={0,1,3,9,27,81,243,729,2187,6561,19683,59049};
int map[151][11];
int dp[2][N];
//前一状态,当前状态
int info_pre[11],info_cur[11];
int n,m,pass;
//初始化
void Init()
{
memset(map,0,sizeof(map));
memset(dp,-1,sizeof(dp));
}
//转化 十进制
int switch_ten(int *p)
{
int i,ans;
for(i=1,ans=0;i<=m;i++){
ans += p[i]*tri[i];
}
return ans;
}
//转化 三进制
void switch_tri(int t,int *p)
{
int i;
for(i=1;i<=m;i++){
p[i] = t%3;
t/=3;
}
return ;
}
void dfs(int i,int j,int cnt,int stata)
{
int k;
dp[i%2][stata] = Max(dp[i%2][stata],cnt);
if(j >= m ) return ;
if(!info_pre[j] && !info_pre[j+1] && !info_cur[j] && !info_cur[j+1]){
// 3*2 排列时
info_cur[j] = info_cur[j+1] = 2;
k = switch_ten(info_cur);
dfs(i,j+2,cnt+1,k);
info_cur[j]=info_cur[j+1]=0;
}
if(j < m-1 && !info_cur[j] && !info_cur[j+1] && !info_cur[j+2]){
// 2*3 排列时
info_cur[j] = info_cur[j+1] = info_cur[j+2] = 2;
k = switch_ten(info_cur);
dfs(i,j+3,cnt+1,k);
info_cur[j] = info_cur[j+1] = info_cur[j+2] = 0;
}
dfs(i,j+1,cnt,stata);
return ;
}
int main()
{
int t,k,i,j,l,stata,ans;
scanf("%d",&t);
while(t--){
Init();
scanf("%d%d%d",&n,&m,&k);
while(k--){
scanf("%d%d",&i,&j);
map[i][j] = 1;
}
for(i=1;i<=m;i++){
info_pre[i] = map[1][i] + 1;
}
stata = switch_ten(info_pre);
dp[1][stata] = 0;
for(i=2;i<=n;i++){
for(j=0;j<tri[m+1];j++)dp[i%2][j] = -1;
for(j=0;j<tri[m+1];j++){
if(dp[(i+1)%2][j] == -1)continue;
switch_tri(j,info_pre);
for(l=1;l<=m;l++){
if(map[i][l])
info_cur[l] = 2;
else info_cur[l] = Max(info_pre[l]-1,0);//就是由着上一行的状态取1或者0
}
pass = dp[(i+1)%2][j];
dfs(i,1,pass,switch_ten(info_cur));
}
}
for(i=0,ans=0;i<tri[m+1];i++){
ans = Max(ans,dp[n%2][i]);
}
printf("%d\n",ans);
}
return 0;
}