JZOJ 4228. 【五校联考3day2】C

题目

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取模后的值。
 

Sample Input

输入1:
1
1 1
输入2:
2
1 1
2 2
输入3:
6
0 0
0 1
0 2
0 3
0 4
0 5
输入4:
5
1 3
-4 6
2 4
1 6
5 9
输入5:
10
175470546 566770243
501153312 923840801
-36922529 -888266785
-587403745 908979876
-483726071 -96937502
991096990 -783436017
766700568 -679180551
-601529754 815529478
961445805 303768338
245415738 325847411

Sample Output

输出1:
4
样例1解释:只有一个祭坛,显然四个方向都可以发射。
输出2:
14
样例2解释:
对于所有的4 × 4 = 16种情况中,只有两种不可行:
1号祭坛向上,2号向左。
1号向右,2号向下
输出3:
144
样例3解释:
最上面的祭坛可以向左中右三个方向连出射线,最下面的祭坛可以向右下左三个方向连出射线,中间4个祭坛可以向左右连出射线,方案数为3 × 2 × 2 × 2 × 2 × 3 = 144。
输出4:
117
样例4解释:
祭坛的位置如图所示:

输出5:
24341
 

Data Constraint

对于前30%的数据,n ≤ 9。
对于前40%的数据,n ≤ 18。
对于前60%的数据,n ≤ 36。
对于前100%的数据,n ≤ 54,对于所有i, j,有x_i ≠ x_j或y_i ≠ y_j,且|x_i|, |y_i| ≤ {10} ^ 9。

大意

    

有n个祭坛,每个祭坛有东西南北四个方向

每个祭坛可以选择一个方向发出射线,保证射线不能相交以及射线不能经过其他祭坛

抽象的来说,如果我们以东方向为x轴,北方向为y轴,建立笛卡尔坐标系,那么每个祭坛将会对应一个整点。每个点向上下左右四个方向之一连出一条射线,这些射线不能相交且射线不能经过除了发出点之外的其他点。

求有多少种方法选择每个祭坛的方向,使得祭坛间不发生冲突

分析

  • 首先我们肯定先想到暴力了

  • 但很显然超时,所以正解是个DP
  • 首先f[l][r][u][d][0||1]表示
     当做到第i个时,向下的祭坛的y坐标最大点是l,向上的祭坛的y坐标最小的点是r,向右的祭坛的y坐标最小点是u,最大点是d
  •  枚举一个最大点
     但是有很多状态时没有用的
     所以达不到O(n^5)
    卡卡常???

 

 

代码

  1 #include <cstdio>
  2 #include<bits/stdc++.h>
  3 #include <iostream>
  4 #include <cmath>
  5 #include <cstring>
  6 #include <algorithm>
  7 #define ll long long
  8 #define N 55
  9 using namespace std;
 10 int f[N][N][N][N][2];
 11 inline int read()
 12 {
 13     int x=0,f=1;char c=getchar();
 14     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
 15     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
 16     return x*f;
 17 }
 18 struct sb
 19 {
 20     int x,y;
 21 }a[N]; //up down left right roll
 22 bool bz;
 23 inline int Max(int x,int y)
 24 {
 25     if (!y) return x;
 26     if (!x) return y;
 27     if (a[x].y>a[y].y)return x;
 28     else return y;
 29 }
 30 inline int Min(int x,int y)
 31 {
 32     if (!y) return x;
 33     if (!x) return y;
 34     if (a[x].y<a[y].y) return x;
 35     else return y;
 36 }
 37 inline bool cmp(sb a,sb b)
 38 {
 39     return a.x<b.x || (a.x==b.x && a.y<b.y);
 40 }
 41 inline bool pd(int i,int j,int k)
 42 {
 43     if (j==1 && a[k].x==a[i+1].x && a[k].y>a[i+1].y) return false; 
 44     if (j==2 && a[k].x==a[i+1].x && a[k].y<a[i+1].y) return false;
 45     if (j==3 && a[k].y==a[i+1].y && a[k].x<a[i+1].x) return false; 
 46     if (j==4 && a[k].y==a[i+1].y && a[k].x>a[i+1].x) return false; 
 47     return true;
 48 }
 49 int main()
 50 {
 51     ios::sync_with_stdio(false);
 52     int n,ans=0,l,r,u,d,i,j;
 53     n=read();
 54     for (int i=1;i<=n;i++)
 55        a[i].x=read(),a[i].y=read();
 56     sort(a+1,a+n+1,cmp);
 57     int p=0,q=1;
 58     f[0][0][0][0][0]=1;
 59 for (register int i=0;i<n;i++)
 60 {
 61     for (register int j=1;j<=4;j++)
 62     {
 63         bz=true;
 64         for (register int k=1;k<=n;k++)
 65             if (!pd(i,j,k))
 66             {
 67                 bz=false;
 68                 break;
 69             }
 70             if (bz)
 71             {
 72             for (register int l=0;l<=i;l++)
 73                 for (register int r=0;r<=i;r++)
 74                     for (register int u=0;u<=i;u++)
 75                         for (register int d=0;d<=i;d++)
 76                         {
 77                             if (f[l][r][u][d][p])
 78                             {
 79                                 if (j==1 && (a[l].y<a[i+1].y || !l))
 80                                   f[l][r][Min(i+1,u)][d][q]=(f[l][r][Min(i+1,u)][d][q]+f[l][r][u][d][p])%998244353;
 81                                 if (j==2 && (a[r].y>a[i+1].y || !r))
 82                                   f[l][r][u][Max(i+1,d)][q]=(f[l][r][u][Max(i+1,d)][q]+f[l][r][u][d][p])%998244353;
 83                                 if (j==3 && ((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)))
 84                                   f[l][r][u][d][q]=(f[l][r][u][d][q]+f[l][r][u][d][p])%998244353;
 85                                 if (j==4)
 86                                   f[Max(i+1,l)][Min(i+1,r)][u][d][q]=(f[Max(i+1,l)][Min(i+1,r)][u][d][q]+f[l][r][u][d][p])%998244353;     
 87                             }   
 88                         }
 89             }
 90         }
 91     p=(p+1)&1;
 92     q=(q+1)&1;
 93     for(register int l=0;l<=n;l++)
 94         for (register int r=0;r<=n;r++)
 95             for (register int u=0;u<=n;u++)
 96                 for (register int d=0;d<=n;d++)
 97                     f[l][r][u][d][q]=0;
 98 }
 99     for(register int l=0;l<=n;l++)
100         for (register int r=0;r<=n;r++)
101             for (register int u=0;u<=n;u++)
102                 for (register int d=0;d<=n;d++)
103                     ans=(ans+f[l][r][u][d][p])%998244353;
104     cout<<ans;
105     return 0;
106 }

 

 

posted @ 2019-01-28 21:56  Melted_czj  阅读(183)  评论(0编辑  收藏  举报
body { background-color:whitesmoke; } // 修改背景颜色为半透明 #home,#sideBarMain>div,#blog-sidecolumn>div>div,.catListView{ background-color:rgba(255,255,255,0); } // 修改其他边框的颜色