SRM 601

唔。。。做悲剧了QAQ 哭瞎! 

250 一开始以为苹果的包和桔子的包不是同一个包。。。500 根本没思路。。950 看的晚了(早看了也写不完。。)


250pt

枚举从每包里那几个,然后找到能拿的最小的苹果数和最大的苹果树(中间那些情况都可以达到) ans += maxapple-minapple+1;


500pt

枚举哪一位开始不同(比如 r),然后dp

dp[2005][3005][2] 表示到第i个数,Aset和Bset异或相差为j,且Aset的第r位是0/1的方案数。

因为从第r位开始不同,Aset和Bset的差j,r位之前必须全为0,且第r位为1;Aset为的第r位是0的;

答案统计一下就完了。


950pt

估计又不是正解的一个YY


先把线段按照起点排序。

因为每个位置只有两个线段重叠,那么假设这两个线段是i和ii

其中i的起点在ii前面。

dp[2][j][k]

当前状态表示为已经处理到pos位置,i这个线段已经放了j个red,k个green。

2是表示滚动数组(pos和i都是另开的变量,如果开在数组里不好表示。其实应该是dp(i,pos,j,k)?,前两维转移幅度太大就滚动了)


刚进入while的时候,要保证(pos在a[i].begin和a[i].end之间,pos在a[ii].begin之前),或者说一直维护着这个

转移:

1、如果a[i].end>=a[ii].begin 那么pos应该转移到a[i].end这个位置,当前pos到a[i].end这一段可以把剩下的颜色全排列放。

     随后变化:

    pos->a[ii].begin (当前位置转移到ii的开始位置)    

    i->ii (dp数组以ii为参考,即i变成ii,原来的i全部处理完毕)

    ii->ii+1; (引入新的ii)

    j->0,k->0 (ii在当前pos位置还没放东西,所以j,k都是0)

2、如果a[i].end<a[ii].begin,那么pos应该转移到a[ii].begin这个位置 (这个转移是100^4,就是枚举这一段是放red和green个数。。。。所以感觉做法不科学,但是貌似这种数据出不出来←_←)

     接下来pos已经在a[ii].begin位置,然后分两种情况 

     2.1、a[i].end<a[ii].end

     2.2、a[i].end>=a[ii].end


2的转移具体怎么搞自行脑补吧233333


代码:


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>

using namespace std;

class WinterAndShopping {
public:
	int getNumber(vector<int> , vector<int> , vector<int> , vector<int> );
};
struct node {
	int n, st, ed;
	int r, g, b;
} a[55];
bool cmp(node a, node b) {
	return a.st < b.st;
}
long long pmod = 1000000007;
long long dp[2][105][105];
int c[505][505];
void prec() {
	int i, j;
	for (i = 0; i < 505; ++i) {
		c[i][0] = c[i][i] = 1;
		for (j = 1; j < i; ++j)
			c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % pmod;
	}
}
int WinterAndShopping::getNumber(vector<int> first, vector<int> red,
		vector<int> green, vector<int> blue) {
	prec();
	int i, j, k, n, pos;
	int ii, jj, kk, rr;
	n = first.size();
	for (i = 0; i < n; ++i) {
		a[i].n = red[i] + green[i] + blue[i];
		a[i].st = first[i];
		a[i].ed = first[i] + a[i].n;
		a[i].r = red[i];
		a[i].g = green[i];
		a[i].b = blue[i];
	}
	sort(a, a + n, cmp);

	int pre, now;
	memset(dp, 0, sizeof(dp));
	dp[0][0][0] = 1;
	pre = 0;
	now = 1;
	i = 0;
	ii = 1;
	pos = a[0].st;
	while (1) {
		if (ii == n)
			break;
/1/
		if (a[ii].st >= a[i].ed) {
			for (j = 0; j <= a[i].r; ++j) {
				for (k = 0; k <= a[i].g; ++k) {
					if (dp[pre][j][k] == 0)
						continue;
					jj = a[i].r - j;
					kk = a[i].g - k;
					rr = a[i].ed - pos - jj - kk;
					if (jj < 0 || kk < 0 || rr < 0)
						continue;
					dp[now][0][0] += dp[pre][j][k] * c[rr + jj + kk][rr] % pmod
							* c[jj + kk][jj] % pmod;
					dp[now][0][0] %= pmod;
				}
			}

			pos = a[ii].st;
			pre = 1 - pre;
			now = 1 - now;
			memset(dp[now], 0, sizeof(dp[now]));
			int tt = max(i, ii) + 1;
			i = ii;
			ii = tt;
			continue;
		}
2//
		int nn = a[ii].st - pos;
		for (j = 0; j <= a[i].r; ++j) {
			for (k = 0; k <= a[i].g; ++k) {
				if (dp[pre][j][k] == 0)
					continue;
				for (jj = 0; jj <= nn && j + jj <= a[i].r; ++jj) {
					for (kk = 0; kk + jj <= nn && k + kk <= a[i].g; ++kk) {
						rr = a[ii].st - pos - jj - kk;
						dp[now][j + jj][k + kk] += dp[pre][j][k] * c[rr + jj
								+ kk][rr] % pmod * c[jj + kk][jj] % pmod;
						dp[now][j + jj][k + kk] %= pmod;
					}
				}
			}
		}
		pos = a[ii].st;
		pre = 1 - pre;
		now = 1 - now;
		memset(dp[now], 0, sizeof(dp[now]));
2.1
		if (a[i].ed < a[ii].ed) {
			for (j = 0; j <= a[i].r; ++j) {
				for (k = 0; k <= a[i].g; ++k) {
					if (dp[pre][j][k] == 0)
						continue;
					jj = a[i].r - j;
					kk = a[i].g - k;
					rr = a[i].ed - pos - jj - kk;
					if (jj < 0 || kk < 0 || rr < 0)
						continue;
					if (jj > a[ii].r)
						continue;
					if (kk > a[ii].g)
						continue;
					if (rr > a[ii].b)
						continue;
					dp[now][jj][kk] += dp[pre][j][k] * c[rr + jj + kk][rr]
							% pmod * c[jj + kk][jj] % pmod;
					dp[now][jj][kk] %= pmod;
				}
			}
			pos = a[i].ed;
			int tt = max(i, ii) + 1;
			i = ii;
			ii = tt;
		} else {
2.2//
			for (j = 0; j <= a[i].r; ++j) {
				for (k = 0; k <= a[i].g; ++k) {
					if (dp[pre][j][k] == 0)
						continue;
					jj = a[ii].r;
					kk = a[ii].g;
					rr = a[ii].b;
					if (j + jj > a[i].r)
						continue;
					if (k + kk > a[i].g)
						continue;
					if (pos - a[i].st - j - k + rr > a[i].b)
						continue;
					dp[now][j + jj][k + kk] += dp[pre][j][k]
							* c[rr + jj + kk][rr] % pmod * c[jj + kk][jj]
							% pmod;
					dp[now][j + jj][k + kk] %= pmod;
				}
			}
			pos = a[ii].ed;
			int tt = max(i, ii) + 1;
			ii = tt;
		}
		pre = 1 - pre;
		now = 1 - now;
		memset(dp[now], 0, sizeof(dp[now]));
	}
	long long ans = 0;
	for (j = 0; j <= a[i].r; ++j) {
		for (k = 0; k <= a[i].g; ++k) {
			if (dp[pre][j][k] == 0)
				continue;
			jj = a[i].r - j;
			kk = a[i].g - k;
			rr = a[i].ed - pos - jj - kk;
			if (jj < 0 || kk < 0 || rr < 0)
				continue;
			ans += dp[pre][j][k] * c[rr + jj + kk][rr] % pmod * c[jj + kk][jj]
					% pmod;
			ans %= pmod;
		}
	}
	return ans;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值