\(\text{Solution}\)

发现每个时刻的状态一定是所有点在一个最外围三角形的内部

设 \(f_{i,j,k,p}\) 表示排列填到第 \(p\) 位,此时图形最外围的三角形是以编号为 \(i,j,k\) 的三角形的方案数

那么考虑这个三角形是怎么来的,于是又两个转移

1.前 \(1~p-1\) 位已经填出了 \(i,j,k\) 这个三角形,那么这一位就可以填这个三角形内部还没填的点

2.到第 \(p\) 位才填出这个三角形,那么这个三角形一定是从一个小三角形转移过来,枚举内部一个点,令它与 \(i,j,k\) 中任意两点组成小三角形转移即可

判断一个点是否在某个三角形内部可以用面积,面积用叉乘算即可

显然这个 \(dp\) 是 \(O(n^5)\) 的

考虑优化,强制枚举的 \(i<j<k\)

这个就优秀很多了,\(JZOJ\) 上可以过,\(LG\) 上要开 \(O\)

\(\text{Code}\)

#include <cstdio>
#include <cmath>
#include <iostream>
#define LL long long
#define re register
using namespace std; const int N = 45;
const LL P = 1e9 + 7;
int n, h[N][N][N];
LL f[N][N][N][N];
struct Point{
double x, y;
inline Point(double xx = 0, double yy = 0){x = xx, y = yy;}
inline Point operator - (const Point &B){return Point(x - B.x, y - B.y);}
}a[N];
inline double Cross(const Point &A, const Point &B){return fabs(A.x * B.y - A.y * B.x);}
inline double Area(int i, int j, int k){return Cross(a[i] - a[j], a[k] - a[j]);}
inline int isIn(int i, int j, int k, int l)
{
return fabs(Area(i, j, k) - Area(i, j, l) - Area(j, k, l) - Area(i, k, l)) <= 1e-6;
} inline void Add(LL &x, LL y){x = (x + y) % P;}
inline void trans(int p, int i, int j, int k, int x, int y, int z)
{
if (z < x) swap(x, z);
if (z < y) swap(y, z);
Add(f[i][j][k][p], f[x][y][z][p - 1]);
} int main()
{
scanf("%d", &n);
for(re int i = 1, x, y; i <= n; i++) scanf("%d%d", &x, &y), a[i] = Point(x, y);
for(re int i = 1; i <= n - 2; i++)
for(re int j = i + 1; j <= n - 1; j++)
for(re int k = j + 1; k <= n; k++)
for(re int l = 1; l <= n; l++)
if (l ^ i && l ^ j && l ^ k) h[i][j][k] += isIn(i, j, k, l);
for(re int i = 1; i <= n - 2; i++)
for(re int j = i + 1; j <= n - 1; j++)
for(re int k = j + 1; k <= n; k++) f[i][j][k][3] = 6;
for(re int p = 4; p <= n; p++)
for(re int i = 1; i <= n - 2; i++)
for(re int j = i + 1; j <= n - 1; j++)
for(re int k = j + 1; k <= n; k++)
{
if (h[i][j][k] - p + 4 > 0) Add(f[i][j][k][p], f[i][j][k][p - 1] * (h[i][j][k] - p + 4) % P);
for(re int l = 1, x, y, z; l <= n; l++)
if (l ^ i && l ^ j && l ^ k && isIn(i, j, k, l))
trans(p, i, j, k, i, j, l), trans(p, i, j, k, i, k, l), trans(p, i, j, k, j, k, l);
}
LL ans = 0;
for(re int i = 1; i <= n - 2; i++)
for(re int j = i + 1; j <= n - 1; j++)
for(re int k = j + 1; k <= n; k++)
ans = (ans + f[i][j][k][n]) % P;
printf("%lld\n", ans);
}

最新文章

  1. Shell入门教程:Shell当中的特殊变量
  2. PHP运行模式
  3. xcode 脚本编译,打包ipa
  4. 解决win7资源监视器不能开启
  5. jquery ready 延迟
  6. Android软键盘弹出时布局问题
  7. Largest Submatrix(动态规划)
  8. Spring——jar包详解
  9. CentOS恢复root口令方法
  10. 腾讯课堂web零基础
  11. 丢掉DDL,我用这招3分钟清空 MySQL 9亿记录数据表
  12. PHP使用prepare(),insert数据时要注意的一点!!!
  13. ES6 中 Promise
  14. C# Note22: 《Effective C#》笔记
  15. 【bug小记】应用跳转白屏
  16. 【协议】1、tcp,http,socket协议介绍
  17. tensorflow实战系列(三)一个完整的例子
  18. 使用VBA批量转换Excel格式,由.xls转换成.xlsx
  19. m4a 转 wav
  20. java实现WC项目

热门文章

  1. 关于linux配置java环境变量问题
  2. 网络工具netstat与ss
  3. formly-form 动态表单
  4. [0x11] 131.直方图中最大的矩形【单调栈】
  5. 【爬虫+数据分析+数据可视化】python数据分析全流程《2021胡润百富榜》榜单数据!
  6. vue3学习第一天
  7. Spring+Quartz+Dom4j实现一个小项目
  8. [OpenCV实战]41 嵌入式计算机视觉设备选择
  9. 焦距的物理尺度、像素尺度之间的转换关系以及35mm等效焦距
  10. group by 语句怎么优化?