Rigid Frameworks
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 381 Accepted Submission(s): 306
Problem Description
Erik Demaine is a Professor in Computer Science at the Massachusetts Institute of Technology. Demaine's research interests range throughout algorithms, from data structures for improving web searches to the geometry of understanding
how proteins fold to the computational difficulty of playing games.
Maid xiaodao is learning theoretical computer science in her spare time, and recently she was fascinated by Professor Erik Demaine's Geometric Folding Algorithms - Linkages, Origami, Polyhedra. The following problem was inspired by this book.
Recall that a graph is a collection of vertices and edges connecting the vertices, and that two vertices connected by an edge are called adjacent. Graphs can be embedded in Euclidean space by associating each vertex with a point in the Euclidean space.
⋅ A flexible graph is an embedding of a graph where it is possible to move one or more vertices continuously so that the distance between at least two nonadjacent vertices is altered while the distances between each pair of adjacent vertices is kept constant.
⋅ A rigid graph is an embedding of a graph which is not flexible. Informally, a graph is rigid if by replacing the vertices with fully rotating hinges and the edges with rods that are unbending and inelastic, no parts of the graph can be moved independently from the rest of the graph.

Sit down and relax, to simplify the problem, let's only consider the planar graphs as grids. The grid graphs embedded in the Euclidean plane are not rigid, as the following animation demonstrates:

However, one can make them rigid by adding diagonal edges to the cells. For example, the following picture shows a 2 × 3 grid graph.

Note that you can add at most one orientation of a diagonal edge in one single cell. In fact, there are 448 ways to make a 2 × 3 grid graph rigid. And now we want to know, how many different rigid m × n grid graph with diagonal edges in total? Dear contestant, could you please find it out?
Maid xiaodao is learning theoretical computer science in her spare time, and recently she was fascinated by Professor Erik Demaine's Geometric Folding Algorithms - Linkages, Origami, Polyhedra. The following problem was inspired by this book.
Recall that a graph is a collection of vertices and edges connecting the vertices, and that two vertices connected by an edge are called adjacent. Graphs can be embedded in Euclidean space by associating each vertex with a point in the Euclidean space.
⋅ A flexible graph is an embedding of a graph where it is possible to move one or more vertices continuously so that the distance between at least two nonadjacent vertices is altered while the distances between each pair of adjacent vertices is kept constant.
⋅ A rigid graph is an embedding of a graph which is not flexible. Informally, a graph is rigid if by replacing the vertices with fully rotating hinges and the edges with rods that are unbending and inelastic, no parts of the graph can be moved independently from the rest of the graph.

Sit down and relax, to simplify the problem, let's only consider the planar graphs as grids. The grid graphs embedded in the Euclidean plane are not rigid, as the following animation demonstrates:

However, one can make them rigid by adding diagonal edges to the cells. For example, the following picture shows a 2 × 3 grid graph.

Note that you can add at most one orientation of a diagonal edge in one single cell. In fact, there are 448 ways to make a 2 × 3 grid graph rigid. And now we want to know, how many different rigid m × n grid graph with diagonal edges in total? Dear contestant, could you please find it out?
Input
There are multiple test cases. For each test case, the first line contains two integer m and n
(1≤m,n≤10)
represented the size of the grid graph.
Output
For each test case, output one integer number in a single line — the number of different rigid m × n grid graph with diagonal edges. The answer could be very large, output it modulo
1000000007(109+7).
Sample Input
1 2 3 2 7 9 10 10
Sample Output
4 448 357533852 935300639
题解
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <map>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
ll c[12][12];
ll dp[12][12];
ll pow3[105];
void init()
{
c[0][0]=1;
for(int i=1;i<=10;i++)
{
c[i][0]=c[i][i]=1;
for(int j=1;j<i;j++)
{
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
//printf("c[%d][%d]==%lld\n",i,j,c[i][j]);
}
}
pow3[0]=1;
for(int i=1;i<=100;i++)
{
pow3[i]=pow3[i-1]*3%mod;
}
//上面预处理出来组合数和3的幂
dp[1][0]=dp[0][1]=1;
for(int i=1;i<=10;i++)
{
for(int j=1;j<=10;j++)
{
dp[i][j]=pow3[i*j];
for(int ii=1;ii<=i;ii++)
{
for(int jj=0;jj<=j;jj++)
{
if(i==ii&&j==jj)
continue;
ll tmp;
tmp=c[i-1][ii-1]*c[j][jj]%mod;
tmp=tmp*dp[ii][jj]%mod;
tmp=tmp*pow3[(i-ii)*(j-jj)]%mod;
dp[i][j]=(dp[i][j]-tmp+mod)%mod;
}
}
}
}
}
int main()
{
init();
int n,m;
while(~scanf("%d %d",&n,&m))
{
printf("%lld\n",dp[n][m]);
}
return 0;
}
http://blog.youkuaiyun.com/dpppbr/article/details/51972196
题意:大家都知道矩形是不稳定的,会变成平行四边形,但是可以在矩形对角线加边,通过构成三角形使这个矩形稳定下来。给一n*m的矩形,可以在单位矩形里加两种对角线(从左上到右下,从左下到右上两种),或者不加对角线,问使这个n*m的矩形稳定下来的方案数。
思路:说思路前先膜一膜鸟神,是鸟神教会了我这道题……万分感谢。
多校官方题解是这样说的:
其实题解已经把思路说好了……只不过太简单了吧……蒟蒻很无奈的。
先说题目为什么可以看做求连通二分图数目,接着说具体解法。
一. 为什么可以看做求连通二分图数目
n*m的矩形有如下性质:对于任意一行,这一行的每一条竖边永远保持平行;同样,对于任意一列,这一行的每一条横边永远保持平行。如题目里的图片所示:
当对一个单位格加上一个斜边的时候,这个小的单位格的形状就不能改变,实质上就是组成这个小单位格的横边和竖边保持着一个垂直关系一旦组成这个小单元格的横边和竖边保持了一个垂直关系,那么和这个横边竖边保持平行关系的变也永远保持一个垂直关系。
以此,可以把这个问题变为二分连通图的计数问题,见下图(自己纯手绘的大家轻喷啊……):
橙色的斜边,使得组成(1,1)格的上下两边(图中的黄边)和第一行的所有竖边(图中的红边)永远保持垂直关系,以及(1,1)格的左右两边和第一列的所有横边永远保持垂直关系(为了不让图太混乱,就没有标出这几条边)。对应到二分图,也是橙色的那条边,意思是第一行和第一列的所有边(因为处在同一行的边永远互相平行,同一列的边也是如此)都保持垂直关系。
要使矩形形状不会发生变化,其实就是任一行和任一列都保持垂直关系。对应到二分图中,就是由行列的点集组成的二分图是连通 的。
二.如何通过计算一个二分图的连通方案数求解
首先,一个n*m的矩阵,由n*m个单位矩阵组成,每个单位矩阵可以加两种对角线(从左上到右下,从左下到右上两种),或者不加对角线,共3种选择,则一个n*m矩阵的总方案数是3^(n*m),只要从所有方案中,除去不合法的方案数,就是合法的方案数。这么做的原因是不合法的方案数更容易求(只要二分图是不连通 的,这个方案就是不合法的)。
设dp[n][m]为使n*m矩阵固定下来的合法方案数。
接着,固定一个点(固定这个点是为了防止计数时的重复计算,待会讲完读者回来想想就明白了),为了方便说明,设这个点是n个点中的第一个点(不是m个点中的点)。枚举这个点所处连通块的情况,只要这个连通块不包含二分图中所有的点,则当前的二分图一定是不连通的,一定是非法方案。
于是状态转移方程是:
其中各元素的取值范围是:1<=n<=10,0<=m<=10,1<=i<=n,0<=j<=m。
试着用一幅图说明这个方程:
n中的点1固定,当连通块大小为i,j时,如何计算非法方案数,从n-1个点中选出i-1个点(因为点1已经被固定了),从m个点中选出j个点,用这i,j个点组成连通块的数量就是![]()
,i+j大小的连通块有dp[i][j]个合法的存在方案,同时,下面的n-i个点和m-j个点有![]()
个组合方式。
重复一下:固定一个点,枚举这个点所处连通块的情况,只要这个连通块不包含二分图中所有的点,则当前的二分图一定是不连通的,一定是非法方案。
一些注意事项:
在枚举i,j的时候,当i==n,j==m的时候,就要停止,不可以让自己减自己;
dp[1][0]应该设为1,代表全二分图没有一条边的情况,因此dp[2][0]……dp[n][0]都得设为0,不然会有重复计算发生,不过我们不需要这样做,因为在枚举过程中,dp[2][0]会减去dp[1][0]时的情况,使自己变回0。
注意事项可能说的不好,详见代码吧