DP HDOJ 5471 Count the Grid

先转化成了离散网格图,然后状态dp即可....

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

#define mp(x, y) make_pair(x, y)
const int maxn = 100;
const int mod = 1e9+7;

struct line
{
	int x1, y1, x2, y2, v;
	line() {}
	line(int x1, int y1, int x2, int y2, int v) : x1(x1), y1(y1), x2(x2), y2(y2), v(v) {}
}l[maxn];

LL dp[2][1 << 10];
int x[maxn];
int y[maxn];
int xlen[maxn];
int ylen[maxn];
int g[maxn][maxn];
int a[maxn][maxn];
int val[maxn][maxn];
LL w1[maxn][maxn];
LL w2[maxn][maxn];
vector<pair<int, int> > vec;
int N, n, m;

int solve(int xx, int yy, int pos1, int pos2)
{
	vec.clear();
	for(int i = 1; i <= N; i++) {
		if(xx >= l[i].x1 && xx <= l[i].x2 && yy >= l[i].y1 && yy <= l[i].y2) {
			vec.push_back(mp(l[i].v, i));
		}
	}
	sort(vec.begin(), vec.end());
	
	int t = 0;
	for(int i = 0; i < vec.size(); i++) {
		t |= 1 << vec[i].second - 1;
		val[pos1][pos2] = min(val[pos1][pos2], l[vec[i].second].v);
		if(i + 1 < vec.size() && vec[i+1].first != vec[i].first) break; 
	}
	return t;
}

LL powmod(LL a, LL b)
{
	LL res = 1, base = a;
	while(b) {
		if(b % 2) res = res * base % mod;
		base = base * base % mod;
		b /= 2;
	}
	return res;
}

void add(LL &x, LL y)
{
	x += y;
	x %= mod;
}

void DP()
{
	memset(dp, 0, sizeof dp);
	add(dp[0][0], powmod(val[1][1] - 1, g[1][1]));
	add(dp[0][a[1][1]], powmod(val[1][1], g[1][1]) - powmod(val[1][1] - 1, g[1][1]));
	
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++) {
			w1[i][j] = powmod(val[i][j]-1, g[i][j]);
			w2[i][j] = (powmod(val[i][j], g[i][j]) - powmod(val[i][j]-1, g[i][j])) % mod;
		}
	
	int now = 0, pre = 1;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			if(i == 1 && j == 1) continue;
			swap(now, pre);
			memset(dp[now], 0, sizeof dp[now]);
			for(int k = 0; k < 1 << N; k++) {
				add(dp[now][k], dp[pre][k]*w1[i][j]%mod);
				add(dp[now][k|a[i][j]], dp[pre][k]*w2[i][j]%mod);
			}
		}
	}
	
	LL ans = dp[now][(1 << N) - 1];
	printf("%lld\n", (ans % mod + mod) % mod);
}

void work()
{
	int cnt1 = 0, cnt2 = 0;
	int x1, y1, x2, y2, v, M, h, w;
	scanf("%d%d%d%d", &h, &w, &M, &N);
	
	x[cnt1++] = 0;
	x[cnt1++] = 2 * h + 1;
	y[cnt2++] = 0;
	y[cnt2++] = 2 * w + 1;
	
	for(int i = 1; i <= N; i++) {
		scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &v);
		l[i] = line(x1, y1, x2, y2, v);
		x1 <<= 1, x2 <<= 1, y1 <<= 1, y2 <<= 1;
		x1--, y1--;
		x2++, y2++;
		x[cnt1++] = x1;
		x[cnt1++] = x2;
		y[cnt2++] = y1;
		y[cnt2++] = y2;
	}
	
	sort(x, x+cnt1);
	sort(y, y+cnt2);
	
	cnt1 = unique(x, x+cnt1) - x;
	cnt2 = unique(y, y+cnt2) - y;
	
	for(int i = 1; i < cnt1; i++) xlen[i] = x[i] - x[i-1];
	for(int i = 1; i < cnt2; i++) ylen[i] = y[i] - y[i-1];
	
	n = cnt1-1;
	m = cnt2-1;
	
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			val[i][j] = M;
	
	int xx = 1, yy = 1;
	for(int i = 1; i <= n; i++) {
		yy = 1;
		for(int j = 1; j <= m; j++) {
			g[i][j] = (xlen[i] / 2) * (ylen[j] / 2);
			a[i][j] = solve(xx, yy, i, j);
			yy += ylen[j] / 2;
		}
		xx += xlen[i] / 2;
	}
	
	DP();
}

int main()
{
	//freopen("data", "r", stdin);
	int _;
	scanf("%d", &_);
	for(int i = 1; i <= _; i++) {
		printf("Case #%d: ", i);
		work();
	}
	
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值