HDU 4804 Campus Design

本文介绍了一个基于状态压缩的动态规划问题及其解决方案。该问题通过增加一维变量来扩展经典的状态压缩DP,使用C++实现了一个具体的例子。文章提供的代码详细展示了如何通过递归和迭代的方法计算特定条件下可能的状态数目。

这个题目还是蛮简单的; 状态压缩的经典题吗  只是增加了一维变量;多开一维搞定

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<cmath>
#define mod  1000000007
using namespace std;

int N,M,C,D;
__int64 dp[4][3000][22];
char map[105][22];

void dfs( int sta,int lev,int stu,int n,int k,__int64 num )
{
    if( sta >= M || k > D)return;
	dfs( sta+1,lev,stu,n,k,num );
	if( map[lev][sta] == '1' && (stu&(1<<sta)) == 0 )
	{
		int t = stu+(1<<sta);
		dp[n][t][k+1]+=num; dp[n][t][k+1] %= mod;
		dfs(sta+1,lev,t,n,k+1,num);
	}
	if( sta + 1 < M && map[lev][sta] == '1' && map[lev][sta+1] == '1' )
	if( (stu&(1<<sta)) == 0 && (stu&(1<<(sta+1))) == 0  )
	{
		int t = stu+(1<<sta); t = t+(1<<(sta+1));
		dp[n][t][k]+=num; dp[n][t][k] %= mod;
		dfs(sta+2,lev,t,n,k,num);
	}
}
void work( )
{
	int i,j,k,s,t=1,num = (1<<M); memset( dp,0,sizeof(dp) ); dp[t][num-1][0] = 1;
	for( i = 1; i <= N; i++ )
	{
        s = t^1;
        for( j = 0; j < num; j++ )
        for( k = 0; k <= D;  k++ )
        {
          if( dp[t][j][k] == 0 )continue; __int64 stu = 0; bool fell = false;
          for( int x = 0; x < M; x++ )
            if( map[i-1][x] != '0' && (j&(1<<x)) == 0 )
            {
				  if( map[i][x] == '0' ) fell = true;
			      else stu += (1<<x);
            }
            if( fell )continue;
			dp[s][stu][k] = dp[t][j][k];
			dfs( 0,i,stu,s,k,dp[t][j][k] );
        }
        for( j = 0; j < num; j++ )
        for( k = 0; k <= D;  k++ )
        dp[t][j][k] = 0;
        t = s;
    }
	__int64 res = 0; int now = 0;
	for( j = 0; j < M; j++ )if( map[N][j] != '0' ) now +=(1<<j);
	for( j = C; j <= D;  j++ ) res += dp[t][now][j],res %= mod;
	printf("%I64d\n",res);
}
int main( )
{
      while( scanf("%d%d%d%d",&N,&M,&C,&D) != EOF ){
		  memset(map,'0',sizeof(map));
          for( int i = 1; i <= N; i++ )
			scanf("%s",map[i]);
		  work( );
	  }
	  return 0;
}
/*
2 3  1 2
111
101
*/

  

转载于:https://www.cnblogs.com/wulangzhou/p/3451756.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值