题目
Description
在远古的YL国大地上,有n个祭坛,每个祭坛上四个方向写有“艄、毜、鼛、瓯”四个大字,其实这在YL国古代分别是“东、南、西、北”的意思。
YL国每年都要举行祈福消灾的祭祀活动,这个时候,每个祭坛都要在艄毜鼛瓯四个方向中选一个方向,祭坛将向这个方向发出一道隐形的光线,如果两个祭坛发出的光线相交,或者祭坛发出的光线经过了别的祭坛,则祭祀不仅不能成功还将遭到上天的惩罚,如果这些条件都满足则祭祀将成功,YL国在接下来的一年内将不会有任何灾难,甚至只会有人出生不会有人死亡。
抽象的来说,如果我们以“艄”方向为x轴,“瓯”方向为y轴,建立笛卡尔坐标系,那么每个祭坛将会对应一个整点。每个点向上下左右四个方向之一连出一条射线,这些射线不能相交且射线不能经过除了发出点之外的其他点}。
现在他们又到了祭祀活动的时候,他们想知道,有多少种方法选择每个祭坛的方向},使得自己的祭祀能成功?输出方案数对998244353取模后的值}。
Input
第一行一个正整数n。
接下来n行,第i + 1行两个整数x_i, y_i,表示第i个祭坛在题目中所述的坐标系下的坐标为(x_i, y_i)。
Output
输出一行一个整数,表示要求的方案数对998244353取模后的值。
解题思路
首先如果有一个点往某一个方向有另一个点,那么这个点就是不可以往这个方向连射线。
然后我们可以将点按x轴从小到大排序处理,这样的我们在DP中只需要处理四个信息:
- 往下的y的最大值
- 往上的y的最小值
- 往右的x的最大值
- 往右的x的最小值
代码
#include<cstdio>
#include<algorithm>
#define rep(i,x,y) for (register int i=x;i<=y;i++)
using namespace std;
const int lw=998244353,N=56;
struct node{int x,y;}a[N];
int f[N][N][N][N][2],ans,n,p,q;
inline bool cmp(node x,node y){return (x.x==y.x)?(x.y<y.y):(x.x<y.x);}
inline bool check(int i,int k,int j){
if(j==0&&a[k].x==a[i+1].x&&a[k].y>a[i+1].y) return 1;
if(j==1&&a[k].x==a[i+1].x&&a[k].y<a[i+1].y) return 1;
if(j==2&&a[k].y==a[i+1].y&&a[k].x<a[i+1].x) return 1;
if(j==3&&a[k].y==a[i+1].y&&a[k].x>a[i+1].x) return 1;
return 0;
}
inline int Min(int x,int y){
if (!y) return x; else if (!x) return y;
return (a[x].y<a[y].y)?x:y;
}
inline int Max(int x,int y){
if (!y) return x; else if (!x) return y;
return (a[x].y>a[y].y)?x:y;
}
int main(){
scanf("%d",&n);
rep(i,1,n) scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+n+1,cmp); f[0][0][0][0][0]=q=1;
rep(i,0,n-1) {
rep(j,0,3){
bool fl=0;
rep(k,1,n) if (check(i,k,j)) {fl=1;break;}
if (fl) continue;
rep(l,0,i) rep(r,0,i) rep(u,0,i) rep(d,0,i) if (f[l][r][u][d][p]){
if(j==0&&(a[l].y<a[i+1].y||!l))
(f[l][r][Min(i+1,u)][d][q]+=f[l][r][u][d][p])%=lw;
if(j==1&&(a[r].y>a[i+1].y||!r))
(f[l][r][u][Max(i+1,d)][q]+=f[l][r][u][d][p])%=lw;
if(j==2&&((a[u].y>a[i+1].y&&a[d].y<a[i+1].y)||(!u&&!d)||(a[u].y>a[i+1].y&&!d)||(a[d].y<a[i+1].y&&!u)))
(f[l][r][u][d][q]+=f[l][r][u][d][p])%=lw;
if(j==3)
(f[Max(i+1,l)][Min(i+1,r)][u][d][q]+=f[l][r][u][d][p])%=lw;
}
}
p=(p+1)&1; q=(p+1)&1;
rep(l,0,n) rep(r,0,n) rep(u,0,n) rep(d,0,n) f[l][r][u][d][q]=0;
}
rep(l,0,n) rep(r,0,n) rep(u,0,n) rep(d,0,n) (ans+=f[l][r][u][d][p])%=lw;
printf("%d",ans);
}

在古老的YL国,为了确保祭祀活动的成功并避免灾难,必须精确计算祭坛建立射线的方向,确保射线不相交且不经过其他祭坛。通过建立笛卡尔坐标系,每个祭坛对应一个整点,利用动态规划算法,考虑射线的方向限制,求解可能的射线布局方案数量。
673

被折叠的 条评论
为什么被折叠?



