[dp] Jzoj P4228 C
题解
- 这题有那么点恶心。。。
- 题目大意:在平面直角坐标系上给定n个点,每个点可以从自己出发一条射线,射线不能相互相交,问方案数
- N<=54,不错不错,可以XJB乱搞一通
- 先按照x作为第一关键字,y作为第二关键字排序
- 设f[i][j][k][l][r]为当前做到第i个祭坛,射线向上的祭坛横坐标最小的祭坛为j,射线向下的祭坛横坐标最大的祭坛为k,射线向右的横坐标最小的为l,横坐标最大的为r的方案数
- 那么考虑一下,如果一个点在另一个点的射程上是不合法的,然后因为一条射线可以无限增长,那么一条向下的射线如果没有左下角向右的射线和右下角向左的射线就是合法的
- 其他的也是同理,那么如果数组开五维会直接炸掉,可以发现i每次至于i-1有关,是递增的,所以第一位可以滚动
- 时间复杂度的话,O(N^5)但是会有很多无用的状态,所以是达不到这个时间复杂度的
代码
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N 60 5 #define mo 998244353 6 using namespace std; 7 struct edge {int x,y;}e[N]; 8 int n,boo,x,y,ans,f[2][N][N][N][N]; 9 bool cmp(edge a,edge b) { return a.x<b.x||a.x==b.x&a.y<b.y; } 10 int min(int x,int y) 11 { 12 if (!x) return y; if (!y) return x; 13 return e[x].y<e[y].y?x:y; 14 } 15 int max(int x,int y) 16 { 17 if (!x) return y; if (!y) return x; 18 return e[x].y>e[y].y?x:y; 19 } 20 bool check(int x,int y,int k) 21 { 22 if (y==1&&e[k].x==e[x].x&&e[k].y>e[x].y) return 0; 23 if (y==2&&e[k].x==e[x].x&&e[k].y<e[x].y) return 0; 24 if (y==3&&e[k].y==e[x].y&&e[k].x<e[x].x) return 0; 25 if (y==4&&e[k].y==e[x].y&&e[k].x>e[x].x) return 0; 26 return 1; 27 } 28 int main() 29 { 30 scanf("%d",&n); 31 for (int i=1;i<=n;i++) scanf("%d%d",&e[i].x,&e[i].y); 32 sort(e+1,e+n+1,cmp),f[0][0][0][0][0]=y=1,x=0; 33 for (int i=1;i<=n;i++) 34 { 35 for (int j=1;j<=4;j++) 36 { 37 boo=0; 38 for (int k=1;k<=n;k++) if (!check(i,j,k)) { boo=1; break; } 39 if (!boo) 40 for (int u=0;u<i;u++) 41 for (int d=0;d<i;d++) 42 for (int l=0;l<i;l++) 43 for (int r=0;r<i;r++) 44 if (f[x][u][d][l][r]) 45 { 46 if (j==1&&(e[u].y<e[i].y||!u)) (f[y][u][d][min(i,l)][r]+=f[x][u][d][l][r])%=mo; 47 if (j==2&&(e[d].y>e[i].y||!d)) (f[y][u][d][l][max(r,i)]+=f[x][u][d][l][r])%=mo; 48 if (j==3&&((e[l].y>e[i].y&&e[r].y<e[i].y)||(!l&&!r)||(e[l].y>e[i].y&&!r)||(e[r].y<e[i].y&&!l))) (f[y][u][d][l][r]+=f[x][u][d][l][r])%=mo; 49 if (j==4) (f[y][max(i,u)][min(i,d)][l][r]+=f[x][u][d][l][r])%=mo; 50 } 51 } 52 x=x^1,y=y^1,memset(f[y],0,sizeof(f[y])); 53 } 54 for (int u=0;u<=n;u++) 55 for (int d=0;d<=n;d++) 56 for (int l=0;l<=n;l++) 57 for (int r=0;r<=n;r++) 58 (ans+=f[x][u][d][l][r])%=mo; 59 printf("%d",ans); 60 }