标签:rectangle str read == term stream getc ring return
[POJ2411]Mondriaan‘s Dream
试题描述
输入
输出
输入示例
1 2 1 3 1 4 2 2 2 3 2 4 2 11 4 11 0 0
输出示例
1 0 1 2 3 5 144 51205
数据规模及约定
见“输入”
题解
经典的轮廓线 dp 问题。将最靠下面并且考虑过的格子的状态进行状压,即,并不是对“最后一行的状态”进行状压,而是对一个“最靠下的轮廓线”进行状压。
这里的“轮廓线”形如“上一行的 k 个元素和这一行的 m-k 个元素”。f(i, j, S) 表示考虑以 (i, j) 为右下角,轮廓线状态为 S 的方案数。具体转移参见《算法竞赛入门经典:训练指南》第六章,开头就是。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <algorithm> using namespace std; int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); } return x * f; } #define maxn 15 #define maxs 2048 #define LL long long int n, m; LL f[maxn][maxn][maxs]; int main() { while(1) { n = read(); m = read(); if(!n && !m) break; memset(f, 0, sizeof(f)); int all = (1 << m) - 1; f[1][1][all] = 1; for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) for(int S = 0; S <= all; S++) if(f[i][j][S]) { if(S & 1) { if(j < m) f[i][j+1][S>>1] += f[i][j][S]; else f[i+1][1][S>>1] += f[i][j][S]; } if(!(S & 1)) { if(j < m) f[i][j+1][S>>1|(1<<m-1)] += f[i][j][S]; else f[i+1][1][S>>1|(1<<m-1)] += f[i][j][S]; } if(j > 1 && !(S >> m - 1 & 1) && (S & 1)) { if(j < m) f[i][j+1][S>>1|(1<<m-1)|(1<<m-2)] += f[i][j][S]; else f[i+1][1][S>>1|(1<<m-1)|(1<<m-2)] += f[i][j][S]; } } printf("%lld\n", f[n+1][1][all]); } return 0; }
标签:rectangle str read == term stream getc ring return
原文地址:http://www.cnblogs.com/xiao-ju-ruo-xjr/p/6946928.html