P1879 [USACO06NOVトウモロコシフィールドコーンフィールド
タイトル説明
ファーマージョン(12≤1≤Mを1≤N 12以下)NによりMからなる豊かな新しい長方形の牧草地を購入した正方形区画を。彼は正方形の数の牛のためのいくつかのおいしいトウモロコシを栽培したいと考えています。残念ながら、正方形のいくつかは不妊であり、植えすることができません。キャニーFJは牛が互いに近接して食べること嫌い植物にどの正方形を選ぶとき、そう、彼は隣接している四角形を選択避けることを知っています。どの2つの選択された四角は、エッジを共有しません。彼はまだ工場にするためにどの正方形として最終的な選択を行っていません。
非常に開放的な男であること、ファーマージョンは植栽のための正方形を選択する方法のためのすべての可能なオプションを検討したいと考えています。彼はとてもオープンマインド彼は有効なオプションとして何の四角を選択しないと考えるということです!ファーマージョンは彼が植物に正方形を選択することができますいくつかの方法を決定するのに役立ちます。
(12≤1≤M、12≤1≤N)農夫ジョンは牧草地の新たな矩形片がM行N列に分割されている新たな牧草地を購入し、各セルは、土地の正方形です。ジョンは彼の牛が楽しむためのいくつかのおいしい牧草地の草の上に植えられたジェリーする予定。
残念ながら、いくつかの非常に不毛の土地は草を使用することはできません。感情のような草の牛のと、排他的な作品、ジョンは二つの隣接地を選択しないように、すなわち、どの2つは共通のエッジの草を持っていません。
あなたは、彼が選択したプログラムを植えるために、そして、草の中に種の総数を総ブロック数を考慮していない場合にはジョンは、知りたいですか?(もちろん、新しい完全に放棄した牧場は、プログラムもあります)
入力形式
最初の行の2つの整数MとNは、スペースで区切られました。
各プロットの状態で説明スペースで区切られたN個の整数を含む各行:M + 1行を介して2。I + 1記載の陸線、i行目、0または1のすべての整数であり、次いで、1 0は、適切な草地をしない示し、十分な肥沃な土地を示しています。
出力フォーマット
牧場割り当て方式が100,000,000の総数で割った整数。
サンプル入力と出力
入力#1
2 3
1 1 1
0 1 0
出力#1
9
[思考]
DP-ような圧力
圧力DPエントリのタイトル様は
、それは非常に簡単ですので、のみ、左右、最大4つの方向ダウンを検討する必要が
それのような[DPを押すと?]
一般データは、特に小さい範囲である成形圧力DPを有する
範囲がデータを見ることができるようになるように
[タイトル]効果
ない上下と矛盾はなく、矛盾についてのシーケンスとの矛盾、与えられていない
数の評価
最初の矛盾は、このプログラムは、重複が発生した芝生エリアと不毛の土地があることを意味
2つの後は、そこにはアップされていないと草ダウン苦しむ意味しますインクルード
[コア]アイデア
与えられた状況不毛の土地との最初の契約は
、その後に発生する可能性のあるすべての状況を列挙
彼は、隣接する周りの草の場合持っているかどうかを判断するために
どのようなマーク
その後、DPプロセスで
内部の次のループでマークされているものを列挙するとアウト
[完了コード】
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int mo = 1e9;
const int Max = 15;
int a;
int f[Max];//这一行草地的情况
int ff[Max][5000]; //第i行选j会有多少种方案
bool s[5000];//左右合不合法
int read()
{
int sum = 0,fg = 1;
char c = getchar();
while(c < '0' || c > '9')
{
if(c == '-')fg = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
{
sum = (sum * 10) + c - '0';
c = getchar();
}
return sum * fg;
}
signed main()
{
int m = read(),n = read();
for(register int i = 1;i <= m;++ i)
for(register int j = 1;j <= n;++ j)
a = read(),f[i] = (f[i] << 1) + a;
int MM = (1 << n);
for(register int i = 0;i < MM;++ i)
s[i] = ((i & (i << 1)) == 0) && ((i & (i >> 1)) == 0);
ff[0][0] = 1;//没有是一定成立的qwq
for(register int i = 1;i <= m;++ i)//枚举到了第几行
for(register int j = 0;j < MM;++ j)//枚举第i行选什么
if(s[j] && (j & f[i]) == j)//如果枚举到选择的j是不会出现左右相邻而且不会在这一行不该出现草的地方出现草
for(register int k = 0;k < MM;++ k)//枚举i-1行选的什么
if((k & j) == 0)//这两行没有相邻的
ff[i][j] = (ff[i][j] + ff[i - 1][k]) % mo;
int M = 0;
for(register int i = 0;i < MM;++ i)
M += ff[m][i],M %= mo;
cout << M << endl;
return 0;
}