Loading

【题解】[USACO20DEC] Sleeping Cows P

非常神的 DP 思维题。

不难想到我们枚举有哪些牛没有匹配,如果牛 \(i\) 没有匹配,那么所有 \(\ge s_i\) 的 牛棚 \(t_j\) 必须匹配。

所以我们只关心最小的没有被匹配的牛。

接下来是这题最关键的一步,我们把牛和牛棚放到一起排序。

因为我们只关心相对大小,放到一起后可以极大程度简化状态。

所以我们可以设计状态 \(f_{i,j,0/1}\),表示枚举到第 \(i\) 个元素,有 \(j\) 头等待匹配的牛,前面是否有牛放弃匹配。

对于第 \(i\) 个元素是牛还是牛棚分开讨论,时间复杂度 \(\mathcal{O}(N^2)\)

#define N 3005
int n, f[N + N][N][2];
struct node{
	int w, op;
	bool operator<(const node o)const{
		if(w != o.w)return w < o.w;
		return op < o.op;
	}
}a[N << 1];

int main() {
	read(n);
	rp(i, n)read(a[i].w), a[i].op = 0;
	rp(i, n)read(a[i + n].w), a[i + n].op = 1;
	sort(a + 1, a + n + n + 1);
	f[0][0][0] = 1;
	rp(i, n + n)rep(j, 0, n){
		if(!a[i].op){
			ad(f[i][j + 1][0], f[i - 1][j][0]), 
			ad(f[i][j + 1][1], f[i - 1][j][1]),
			ad(f[i][j][1], f[i - 1][j][1]);
			ad(f[i][j][1], f[i - 1][j][0]);
		}
		else{
			ad(f[i][j][0], f[i - 1][j + 1][0] * (j + 1LL) % P);
			ad(f[i][j][0], f[i - 1][j][0]);
			ad(f[i][j][1], f[i - 1][j + 1][1] * (j + 1LL) % P);
		}
	}
	cout << (f[n + n][0][0] + f[n + n][0][1]) % P << endl;
	return 0;
}
posted @ 2022-02-07 15:26  7KByte  阅读(43)  评论(0编辑  收藏  举报