标签: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