Educational Codeforces Round 32 F. Connecting Vertices 區間DP
阿新 • • 發佈:2018-12-12
Description 給你n個點,給一張鄰接矩陣表示點與點的關係,若a[i][j]=1,則表示i和j有邊相連,要求不允許存在兩條邊(i,j),(x,y)滿足i < x < j < y,問有多少種方案。
Sample Input 3 0 0 1 0 0 1 1 1 0
Sample Output 1
計數題啊。。。 首先考慮區間DP。 設f[i][j]為i到j有邊相連,i和j之間的邊都連好了的方案數。 設g[i][j]為i到j沒有邊相連,i和j之間的邊都連好了的方案數。 對於每一個l,r列舉斷點,對於f的轉移: 對於g的轉移: 然後統計f[1][n]和g[1][n]即可。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const LL mod = 1e9 + 7; int _min(int x, int y) {return x < y ? x : y;} int _max(int x, int y) {return x > y ? x : y;} int read() { int s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar(); return s * f; } int a[510][510]; LL f[510][510], g[510][510]; int main() { int n = read(); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) a[i][j] = read(); for(int i = 1; i <= n; i++) f[i][i] = 1; for(int len = 2; len <= n; len++) { for(int l = 1; l <= n - len + 1; l++) { int r = l + len - 1; if(a[l][r]) { for(int k = l; k < r; k++) (f[l][r] += (f[l][k] + g[l][k]) * (g[k + 1][r] + f[k + 1][r]) % mod) %= mod; } for(int k = l + 1; k < r; k++) if(a[l][k]){ (g[l][r] += f[l][k] * (f[k][r] + g[k][r])) %= mod; } } } LL ans = f[1][n]; (ans += g[1][n]) %= mod; printf("%lld\n", ans); return 0; }