• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

学习笔记[AGC039E] Pairing Points

武飞扬头像
仰望星空的蚂蚁
帮助1

太复杂了,做不动。

设第 2 n 2n 2n个点与 k k k相连,这样把点分成了左右两个集合,一定存在左边的 x x x与右边的 y y y相连的一条边,并且这个结构有一个比较优美的性质,左右相连的边的点的编号应该是单调,否则会存在环。那么我们取最靠近上端的那条边。

那么我们用 [ i : j ] ( k ) [i:j](k) [i:j](k)表示 [ i : j ] [i:j] [i:j]这一段圆弧, k k k向圆弧外的一个点连了边的方案数。如果我们直接将问题拆分成 [ i : k − 1 ] ( x ) [i:k-1](x) [i:k1](x) [ k 1 : j ] ( y ) [k 1:j](y) [k 1:j](y)那么显然这样的方案是合法的,因为任意一条边都能和 ( x , y ) (x,y) (x,y)互达并且不存在环。显然我们只遗漏了 x x x下端点和 y y y下端点连边的情况,而我们事实上可以选择一条割线,使得将 ( ? , k ) (?,k) (?,k)删去后变成不连通的两部分,更形象的讲,删去 ( ? , k ) (?,k) (?,k)后与 ( x , y ) (x,y) (x,y)联通的一定是上端两段圆弧,那么枚举 p p p, q q q,显然 p p p, q q q上端只存在 ( x , y ) (x,y) (x,y)一条横边,那么可以拆分成 [ i : p ] ( x ) [i:p](x) [i:p](x) [ q : j ] ( y ) [q:j](y) [q:j](y),下端圆弧因为不存在向上的边因此直接拆成 [ p 1 : q − 1 ] ( k ) [p 1:q-1](k) [p 1:q1](k)

复杂度 O ( n 7 ) O(n^7) O(n7)。据说常数极小。

#include<bits/stdc  .h>
#define ll long long
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define db long double
#define cpx complex<db>
using namespace std;
int n;
char a[45][45];
ll dp[45][45][45],res;
ll dfs(int i,int j,int k){
	if(k<i||k>j)return 0;
	if(i==j)return 1;
	if(i==k||j==k)return 0;
	if(~dp[i][j][k])return dp[i][j][k];
	ll res(0);
	for(int x=i;x<k;x  ){
		for(int y=k 1;y<=j;y  ){
			if(a[x][y]=='1'){
				for(int p=x;p<k;p  ){
					for(int q=k 1;q<=y;q  ){
						res =dfs(i,p,x)*dfs(q,j,y)*dfs(p 1,q-1,k);
					}
				}
			}
		}
	}
	return dp[i][j][k]=res;
}
int main(){
	memset(dp,-1,sizeof dp);
	scanf("%d",&n),n<<=1;
	for(int i=1;i<=n;i  ){
		scanf("%s",a[i] 1);
	}for(int i=1;i<n;i  )if(a[n][i]=='1')res =dfs(1,n-1,i);
	printf("%lld",res);
}
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfibejh
系列文章
更多 icon
同类精品
更多 icon
继续加载