HDU 4804 Campus Design(经典轮廓线问题扩展)



题意:给定一个图,0是不能放的,然后现在有1X1和1X2方块,最后铺满该图,使得1X1使用次数在C到D之间,1X2次数随便,问有几种放法。

思路:经典问题多米诺的拓展,状态多开一维表示用了几个1*1砖块即可,注意位运算的优先级。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#define eps 1e-6
#define LL long long
#define pii (pair<int, int>)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;
int n, m, cur, C, D;
const int maxn = 11;
LL d[2][1<<maxn][25];
char G[150][maxn];

int main() {
//	freopen("input.txt", "r", stdin);
	while(scanf("%d%d%d%d", &n, &m, &C, &D) == 4) {
		for(int i = 0; i < n; i++) {
			getchar();
			for(int j = 0; j < m; j++) scanf("%c", &G[i][j]);
		}
		cur = 0;
		memset(d[cur], 0, sizeof(d[cur]));
		d[cur][(1<<m)-1][0] = 1;
		for(int i = 0; i < n; i++)
			for(int j = 0; j < m; j++) {
				cur ^= 1;
				memset(d[cur], 0, sizeof(d[cur]));
				for(int k = 0; k < (1<<m); k++) {
					if(G[i][j] == '1') {
						if((k&(1<<(m-1))) || (i&&G[i-1][j]=='0')) for(int l = 0; l <= D; l++)
								d[cur][(k<<1)&(~(1<<m))][l] += d[1-cur][k][l], d[cur][(k<<1)&(~(1<<m))][l] %= mod; //不放
						if(i && !(k&(1<<(m-1))) && G[i-1][j]!='0') for(int l = 0; l <= D; l++)
								d[cur][(k<<1)+1][l] += d[1-cur][k][l], d[cur][(k<<1)+1][l] %= mod; //竖放1*2
						if(j && G[i][j-1]!='0' && !(k&1) && ((k&(1<<(m-1)))||i&&G[i-1][j]=='0')) for(int l = 0; l <= D; l++)
								d[cur][(k<<1)&(~(1<<m))|3][l] += d[1-cur][k][l], d[cur][(k<<1)&(~(1<<m))|3][l] %= mod; //右放1*2
						if((k&(1<<(m-1))) || i&&G[i-1][j]=='0') for(int l = 0; l < D; l++)
								d[cur][((k<<1)&(~(1<<m)))+1][l+1] += d[1-cur][k][l], d[cur][((k<<1)&(~(1<<m)))+1][l+1] %= mod; //放1*1
					}
					else {
						if((k&(1<<(m-1))) || i&&G[i-1][j]=='0') for(int l = 0; l <= D; l++)
							d[cur][(k<<1)&(~(1<<m))][l] += d[1-cur][k][l], d[cur][(k<<1)&(~(1<<m))][l] %= mod;
					}
				}
			}
		LL ans = 0;
		int s = (1<<m)-1;
		for(int i = 0; i < m; i++) if(G[n-1][i] == '0') s ^= (1<<(m-i-1));
		//cout << s << endl;
		for(int i = C; i <= D; i++) ans += d[cur][s][i], ans %= mod;
		//cout << d[1-cur][s][0] << endl;
		cout << ans << endl;
		//for(int i = C; i <= D; i++) cout << d[1-cur][2][0] << endl;
		//cout << G[0][0] << G[0][1] << endl;
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-20 01:17:37

HDU 4804 Campus Design(经典轮廓线问题扩展)的相关文章

hdu 4804 Campus Design 轮廓线dp

题意: 给出一个n*m的01矩阵,其中要求把矩阵里面的1用1*1或1*2的砖块铺满,矩阵里面的0为障碍物,问使用1*1的砖块数>=c && <=d 的方案有多少种. 限制: 1 <= n <= 100; 1 <= m <= 10; 1 <= c <= d <= 20; 思路: 因为 1 <= m <= 10 所以可以采用轮廓线dp, 具体状态解释在代码中说明. /*hdu 4804 Campus Design 轮廓线dp 题

HDU 4804 Campus Design(插头DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4804 题意:给定一个图,0是不能放的,然后现在有1X1和1X2方块,最后铺满该图,使得1X1使用次数在C到D之间,1X2次数随便,问有几种放法 思路:插头DP的变形,只要多考虑1X1的情况即可,然后DP多开一维表示使用1X1的个数 代码: #include <stdio.h> #include <string.h> #include <algorithm> #include

hdu 4804 Campus Design(插头dp)

题目链接:hdu 4804 Campus Design 题目大意:有1?2的木块无穷个,要求在给定的图n?m的图上,用1?2和1?1的木块铺满,图上的0表示不需要铺的位置,1表示必须要铺的位置.并且1?1的使用数量必须在c到d之间.求总方案数. 解题思路:和uva11270一样的做法,只是需要多添加一位状态来表示用掉1得个数,以及要对当前位置判断是否为可放. #include <cstdio> #include <cstring> #include <algorithm>

HDU 4804 Campus Design

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4804 题意:给你一个n*m的棋盘,让你用1x1和1x2的方块填满它,棋盘有些地方不能放方块,1x1的方块使用有限制,问一共有多少种方法填满 dp多开一维存放1x1的个数,之后就是正常的插头dp思路 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cm

【插头DP】HDU 4804 Campus Design

通道:http://acm.hdu.edu.cn/showproblem.php?pid=4804

hdu 1007 Quoit Design (经典分治 求最近点对)

Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat rings are pitched at some toys, with all the toys encircled awarded.In the field of Cyberground, the position of each toy is fixed, and the ring is carefull

HDU 3998 Sequence(经典问题,最长上升子序列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3998 解题报告:求一个数列的最长上升子序列,并求像这样长的不相交的子序列最多有多少个. 我用的是最简单的方法,就是每次求最长上升子序列,然后每次将求得的子序列从数列里面删掉,然后再对剩下的数列求最长上升子序列,如果求得的子序列的长度比第一次求得的长度小的话,就退出.不过我这题卡了很久,原因就是因为用这种方法求的过程中,用到了很多变量,但是没有注意每一步求最长上升子序列的时候都要进行初始化,哎. Vi

HDU 1007 Quoit Design (分治)

Quoit Design Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat rings are pitched at some toys, with all the toys encircled awarded. In the field of Cyberground, the position of each toy is fixed, and the ri

hdu 1007 Quoit Design 分治求最近点对

Quoit Design Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 29344    Accepted Submission(s): 7688 Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat