关于状压DP的一点小小问题
  • 板块学术版
  • 楼主wyf_sinon
  • 当前回复1
  • 已保存回复1
  • 发布时间2024/7/13 20:12
  • 上次更新2024/7/13 21:13:02
查看原帖
关于状压DP的一点小小问题
540177
wyf_sinon楼主2024/7/13 20:12

例如acwing291

思路(其实是结合老师的课件悟出来的

状态: F[i][j]表示前i-1列放满了 第i列横着放的矩形状压为j之后的方案数

转移:F[i][j]=sigema(F[i-1][k]) ; k枚举i-1列的横条 合法条件:k&j==1 对于j 连续的空位个数为偶数 否侧无法用竖条赛满

但是这里我有个问题 我的1*2肯定是从1 * 1 转移过来的 但是1 * 1 显然不合法为0 那么1 * 2 是怎么转移出来的

然后代码瞎写的 请求dalao指点

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=13;
int n,m;
int f[N][(1<<N)];//前i-1列已经摆放好 且从i-1列延伸到第i列的长条状态为j 的方案数 因此我们将横条的状态进行状压 
signed main()
{
	while(1)
	{
		scanf("%lld%lld",&n,&m);  
		if( !n && !m ) return 0;  
		memset(f,0,sizeof f);     
        f[0][0]=1;
        for(int i=2;i<=m;i+=2) f[i][1]=1;//预处理?
		for(int i=1;i<=m+1;i++) //阶段 枚举前i列 
		{
			for(int j = 0 ; j < (1<<n) ; ++j ) //状态 
			{
				for(int k = 0 ; k < (1<<n) ; ++k ) // 决策 
				{
                    int res=0;
                    int t=k;
                    bool flag=0;
                    do
                    {
                        if(!(t&1)) res++;
                        else 
                        {
                            if(res&1) // 连续的空位为偶数 否侧无法填完  
                            { 
                                flag=1; 
                                break; 
                            } 
                            res=0; 
                        } 
                        t>>=1; 
                    } while(t);          
                    if(res&1) continue;  
                    if(flag) continue;   
					if( ( j & k ) == 0 ) //第i-2延伸的与i-1延伸的不重复
                    {                    
                        // printf("J:%lld K:%lld I:%lld \n",j,k,i);  
                        f[i][j]+=f[i-1][k] ;                      
                    } 
				}     
                // printf("I:%lld J:%lld Val:%lld\n",i,j,f[i][j]);   
			} 
		} 
        printf("%lld\n",f[m+1][0]);//前m列 顺序已确定 延伸到m+1为0 
        // puts(""); 
	} 
} 
//f[i][j]=sigema(f[i][k]) 其中 k 为合法状态 
2024/7/13 20:12
加载中...