HDU4804 Campus Design 轮廓线dp

跟上面那篇轮廓线dp是一样的,但是多了两个条件,一个是在原图上可能有些点是不能放的(即障碍),所以转移的时候要多一个判断color[i][j]是不是等于1什么的,另外一个是我们可以有多的1*1的骨牌,1*1的骨牌使用数量一定要在[c,d]之间,所以状态加多一维,转移的时候多一种情况(放1的)。那么怎么初始化呢?有两种方法,一种是dp[0][0][d]=1,最后的答案的因为一定要用[c,d]之间,所以答案是dp[(t+1)&1][0][0~d-c].另外一种是dp[0][0][c~d]=1,最后答案是dp[(t+1)&1][0][0]

学了就觉得很简单,60行不到的代码让我们和银奖失之交臂,痛心疾首呀~

下面放一发代码~

#pragma warning(disable:4996)
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<cmath>
#include<cstdio>
#define mod 1000000007
#define maxn 100
#define maxm 10
using namespace std;

char color[maxn + 50][maxm + 5];
int dp[2][1 << (maxm+1)][25];
int n, m, c, d;

int main()
{
	while (~scanf("%d%d%d%d", &n, &m, &c, &d))
	{
		for (int i = 0; i < n; i++) scanf("%s", color[i]);
		memset(dp, 0, sizeof(dp));
		dp[0][0][d] = 1;
		int t = 0;
		for (int i = 0; i < n; i++){
			for (int j = 0; j < m; j++){
				t = i*m + j;
				memset(dp[(t + 1) & 1], 0, sizeof(dp[(t + 1) & 1]));
				for (int k = 0; k < 1 << m; k++){
					for (int r = 0; r <= d; r++){
						if ((k >> j) & 1 || color[i][j] == '0'){
							dp[(t + 1) & 1][k&~(1 << j)][r] = (dp[t & 1][k][r] + dp[(t + 1) & 1][k&~(1 << j)][r]) % mod;
						}
						else{
							if (j + 1 < m && color[i][j + 1] == '1'&& !(k >> (j + 1) & 1)){
								dp[(t + 1) & 1][k | (1 << (j + 1))][r] = (dp[t & 1][k][r] + dp[(t + 1) & 1][k | (1 << (j + 1))][r]) % mod;
							}
							if (i + 1 < n&&color[i + 1][j] == '1'){
								dp[(t + 1) & 1][k | (1 << j)][r] = (dp[t & 1][k][r] + dp[(t + 1) & 1][k | (1 << j)][r]) % mod;
							}
							if (r > 0){
								dp[(t + 1) & 1][k][r - 1] = (dp[t & 1][k][r] + dp[(t + 1) & 1][k][r - 1]) % mod;
							}
						}
					}
				}
			}
		}
		int ans = 0;
		for (int i = d - c; i >= 0; i--){
			ans = (ans + dp[(t + 1) & 1][0][i]) % mod;
		}
		printf("%d
", ans);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/chanme/p/3561326.html