首先可以发现的是,因为两条线段不能在除了端点处相交,因此整个多边形最终一定会被连接成最上方由若干条线段在端点处相交连成,每条线段下方又是一个子结构。

因此你会发现,每个合法的状态都能被分成两个合法的子结构,因此可以考虑使用区间 \(dp\) 来解决这个问题。

首先,我们简单地考虑令 \(dp_{i, j}\) 表示只使用 \(i, j\) 这个区间之间的边将 \(i, j\) 这个区间联通的方案。

  • 直接在 \(i, j\) 之间连边。

那么枚举每个 \(k\) 做为中间的断点,那么就有转移:

\[dp_{i, j} = \sum\limits_{k = i} ^ {j - 1} dp_{i, k} \times dp_{k + 1, j}(a_{i, j} = 1)
\]
  • 不直接在 \(i, j\) 之间连边。

同样考虑枚举中间的端点 \(k\),那么一个合法的方案就会被描述为用 \(i \sim k\) 之间的边联通 \(i \sim k\) 另一边类似,于是有转移:

\[dp_{i, j} = \sum\limits_{k = i + 1} ^ {j - 1} dp_{i, k} \times dp_{k, j}
\]

但其实你会发现,同一个断点的方案会被所有最外层线段交点的位置计算一次,那么一个最简单的想法就是让这个方案只被计算一次。

于此同时你可以发现我们目前只会计算直接连接两个端点的方案,因此让这个方案在左上边第一个线段交点的位置计算一次是一个不赖的选择。

因此我们需要改写一下 \(dp\) 的状态,令 \(dp_{i, j, 0 / 1}\) 分别表示直接连接 \(i, j\) 和不直接连接 \(i, j\) 的方案。

那么这里的转移就应该变为:

\[dp_{i, j, 1} = \sum\limits_{k = i + 1} ^ {j - 1} (dp_{i, k, 0} + dp_{i, k, 1}) \times dp_{k, j, 0}
\]

对应地改写第一条转移方程即可。

复杂度 \(O(n ^ 3)\)。

#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l; i <= r; ++i)
const int N = 500 + 5;
const int Mod = 1e9 + 7;
int n, a[N][N], f[N][N], dp[N][N][2];
int read() {
char c; int x = 0, f = 1;
c = getchar();
while (c > '9' || c < '0') { if(c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int Inc(int a, int b) { return (a += b) >= Mod ? a - Mod : a;}
int Mul(int a, int b) { return 1ll * a * b % Mod;}
int main() {
n = read();
rep(i, 1, n) rep(j, 1, n) a[i][j] = read();
rep(i, 1, n) dp[i][i][1] = f[i][i] = 1;
rep(i, 1, n) dp[i][i + 1][0] = f[i][i + 1] = a[i][i + 1];
rep(len, 3, n) rep(i, 1, n) {
int j = i + len - 1; if(j > n) break;
rep(k, i, j - 1) if(a[i][j]) dp[i][j][0] = Inc(dp[i][j][0], Mul(f[i][k], f[k + 1][j]));
rep(k, i + 1, j - 1) dp[i][j][1] = Inc(dp[i][j][1], Mul(f[i][k], dp[k][j][0]));
f[i][j] = Inc(dp[i][j][0], dp[i][j][1]);
}
printf("%d", f[1][n]);
return 0;
}

值得一提的是,\(dp\) 的转移一定要想办法将这个问题拆解成已经解决的子问题的结构,例如区间 \(dp\) 中就一定要能描述为左右两个合法区间的结合或其他的意义。

CF888F Connecting Vertices的更多相关文章

  1. Connecting Vertices CodeForces - 888F (图论,计数)

    链接 大意: 给定邻接表表示两点是否可以连接, 要求将图连成树, 且边不相交的方案数 n范围比较小, 可以直接区间dp $f[l][r]$表示答案, $g[l][r]$表示区间[l,r]全部连通且l, ...

  2. POJ Minimum Cut

    Minimum Cut Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 9302   Accepted: 3902 Case ...

  3. POJ 2914 Minimum Cut

    Minimum Cut Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 9319   Accepted: 3910 Case ...

  4. 论文笔记之:Large Scale Distributed Semi-Supervised Learning Using Streaming Approximation

    Large Scale Distributed Semi-Supervised Learning Using Streaming Approximation Google  2016.10.06 官方 ...

  5. CodeForces 682C Alyona and the Tree (树+dfs)

    Alyona and the Tree 题目链接: http://acm.hust.edu.cn/vjudge/contest/121333#problem/C Description Alyona ...

  6. POJ_2914_Minimum_Cut_(Stoer_Wagner)

    描述 http://poj.org/problem?id=2914 求无向图中最小割. Minimum Cut Time Limit: 10000MS   Memory Limit: 65536K T ...

  7. POJ 2914 Minimum Cut 最小割图论

    Description Given an undirected graph, in which two vertices can be connected by multiple edges, wha ...

  8. Shorten Diameter

    Shorten Diameter Time limit : 2sec / Stack limit : 256MB / Memory limit : 256MB Score : 600 points P ...

  9. 2015 多校联赛 ——HDU5302(构造)

    Connect the Graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

随机推荐

  1. Chapter 13 Standardization and The Parametric G-formula

    目录 13.1 Standardization as an alternative to IP weighting 13.2 Estimating the mean outcome via model ...

  2. Java实习生常规技术面试题每日十题Java基础(四)

    目录 1.String 和StringBuffer的区别. 2.数组有没有length()这个方法? String有没有length()这个方法? 3.final, finally, finalize ...

  3. 编写Java程序_输入一个5位数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同。

    要求: 输入一个5位数,判断它是不是回文数.即12321是回文数,个位与万位相同,十位与千位相同. 实现代码: package kaoshi; import java.util.Scanner; pu ...

  4. 使用JavaScript 中的Math对象和勾股定理公式,计算鼠标的位置与页面图片中心点的距离,根据距离对页面上的图片进行放大或缩小处理。距离远时图片放大,距离近时图片缩小

    查看本章节 查看作业目录 需求说明: 使用JavaScript 中的Math对象和勾股定理公式,计算鼠标的位置与页面图片中心点的距离,根据距离对页面上的图片进行放大或缩小处理.距离远时图片放大,距离近 ...

  5. Ranger-Usersync安装

    Ranger-Usersync安装, 配置数据源Unix,Usersync从Unix拉取Users/Groups的数据源, 对应的Ranger版本0.6.0. IP/机器名 安装软件 运行进程 zdh ...

  6. HDU ACM 8.13 T2 的 O(m)做法

    前言 由于本人比较拉所以看起来很啰嗦,将就看就好. 题目大意 \(n\)种包,每个包里面有一大一小两个球,选小球的代价是\(1\),大球的代价是\(2\),可以都不选,若一次性买两个包,则可以优惠\( ...

  7. Centos 7.6关闭selinux

    查看selinux状态 [root@localhost ~]# sestatus SELinux status: enabled SELinuxfs mount: /sys/fs/selinux SE ...

  8. 51 Nod 1083 矩阵取数问题(动态规划)

    原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1083 题目分析:通过读题发现我们只能往右边或者下边走,意味着 ...

  9. kafka学习笔记(三)kafka的使用技巧

    概述 上一篇随笔主要介绍了kafka的基本使用包括集群参数,生产者基本使用,consumer基本使用,现在来介绍一下kafka的使用技巧. 分区机制 我们在使用 Apache Kafka 生产和消费消 ...

  10. CTF-sql-order by盲注

    本文章只讨论了order by盲注,关于order by的报错等注入不在本文章讨论范围,另有文章. 让我们先来看看本文章所使用的表的内容,如下图: 接下来先了解一下order by的基础知识: ord ...