codeforces 567F Mausoleum (dp)

本文介绍了一道涉及动态规划和区间操作的编程题目。通过使用动态规划数组f[i][j]表示使用前i个数字放置到第j位的方案数,解决了一种具有特定比较限制的序列构造问题。代码中包含了预处理输入、状态转移和边界条件检查等关键步骤,最终计算出所有可能的序列数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

l i n k link link:添加链接描述


f l , r f_{l,r} fl,r 表示左右分别放到 l 、 r l、r lr 的位置每次转移的时候考虑一下限制就行了。

如果用 f i , j f_{i,j} fi,j 表示用了前 i i i 个数字放到第 j j j 也等价,可以用 i , j i,j i,j 推出 l , r l,r l,r 细节很多的一道题

#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define fr first
#define se second
#define ll long long
#define gg {flag = false;break;}
int rd() {
    int sum = 0;char c = getchar();bool flag = true;
    while(c < '0' || c > '9') {if(c == '-') flag = false;c = getchar();}
    while(c >= '0' && c <= '9') sum = sum * 10 + c - 48,c = getchar();	
    if(flag) return sum;
    else return -sum;
}
int n,q;
ll f[100][100];
pair<pair<int,int>,int>h[110]; 
// 1:<  2:<=  3:=  4:> 5:>=
void pre() {
	char c;
	int i = 1;
	while(i <= q) {
		h[i].fr.fr = rd();
		c = getchar(); while(c == ' ') c = getchar();
		if(c == '<') h[i].se = 1;
		if(c == '=') h[i].se = 3;
		if(c == '>') h[i].se = 4;
		c = getchar(); if(c == '=') h[i].se++;
		h[i].fr.se = rd();
		
		if(h[i].fr.fr > h[i].fr.se) {
			swap( h[i].fr.fr , h[i].fr.se );
			if(h[i].se == 1 || h[i].se == 2) h[i].se += 3;
			else if(h[i].se == 4 || h[i].se == 5) h[i].se -= 3;
		}
		if(h[i].fr.fr == h[i].fr.se) 
		    if(h[i].se == 1 || h[i].se == 4) {printf("0\n");exit(0);}
		    else q--;
		else i++;
	}
	sort(h+1,h+q+1);
}
void work() {
	ll ans = 0;
	f[0][2*n+1] = 1;
	rep(i,0,n-1) rep(l,0,2*i) {
		int r = 2*n+1-(2*i-l); bool flag = true;
		rep(k,1,q) if(h[k].fr.fr == l+1){
			if(h[k].fr.se > r-1) {if(h[k].se <= 3) gg;}
			else if(h[k].fr.se == r-1) {if(h[k].se == 1 || h[k].se == 4) gg;}
			else if(h[k].se >= 3) gg;
		} 
		if(flag)
		rep(k,1,q) if(h[k].fr.fr == r-1) if(h[k].se <= 3) gg;
		if(flag && i != n-1) f[l+1][r-1] += f[l][r];
		
		flag = true;
		rep(k,1,q) if(h[k].fr.fr == l+1) {
			if(h[k].fr.se == l+2) {if(h[k].se == 1 || h[k].se == 4) gg;}
			else if(h[k].fr.se >= r) {if(h[k].se <= 3) gg;}
			else {if(h[k].se >= 3)gg;}
	    }
	    if(flag) rep(k,1,q) if(h[k].fr.fr == l+2) {
	    	if(h[k].fr.se >= r) {if(h[k].se <= 3)gg;}
	    	else {if(h[k].se >= 3) gg;}
		}
		if(flag) f[l+2][r] += f[l][r];
		
		flag = true;
		rep(k,1,q) if(h[k].fr.fr == r-2) {
			if(h[k].fr.se == r-1) {if(h[k].se == 1 || h[k].se == 4) gg; }
			else if(h[k].se <= 3) gg;
		}
		else if(h[k].fr.fr == r-1) if(h[k].se <= 3) gg;
		if(i != n-1 && flag) f[l][r-2] += f[l][r];
    }
	rep(i,0,2*n) ans += f[i][i+1];
	printf("%lld\n",ans);
}
int main() {
    n = rd(); q = rd();
    pre();
    work(); 
	return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值