Luo Gu [P1879] [[USACO06NOV] corn fields Corn Fields]

topic:

link

Ideas:

Q: How can think of is like pressure DP ?

A: That is because (I read the label) \ (. 1 ≤ M ≤ 12 is;. 1 ≤ N ≤ 12 is \) , \ (12 is 2 ^ {} \) , but only. . . (Win7 Calculator use) \ (4096 \) Well! If then shaped pressure DP can also optimize temporal


Determine the status:

\ (f_ {i, j} \) represents the \ (I \) scheme row (for the program, which is the program the answer is program number) \ (J \) (a binary number, decimal storing , the \ (K \) bits are \ (1/0 \) (binary) indicates selected \ (/ \) not selected number of the scheme).

Determining the transfer equation:

Disclaimer: The following \ (j, k \) is a legitimate program

Has been set to \ (I \) row, the solution is at this time \ (J \) , the program line is \ (K \) .

There is a special condition (boundary): \ (= I. 1 \) .

Since it is the first line, so that the legitimate program is correct, so the boundary is:
\ [\ Large {{F_. 1, J =. 1}} \]

You can easily imagine the number of legal program of the Bank's program is on the line all the legal number of programs, namely:

\[\Large {f_{i,j} = f_{i,j}+f_{i - 1,k}}\]

Code:

Disclaimer: the optimization may not use eggs. . .

const int N = 15;
int n, m;
int f[N][(1 << N)];
int st[1 << N];   //一个小小的优化数组
int a[N];
int tot;

void _init()     //一个小小的优化,判断此方案  在这一行  是不是合法的
{
    for (int i = 0; i < (1 << m); i++)
    {
        if (i & (i << 1)) continue;
        st[++tot] = i;
    }
}

int main()
{
    scanf ("%d%d", &n, &m);
    for (int j = 1; j <= n; j++)
        for (int i = m - 1; i >= 0; i--)
        {
            int x;
            scanf ("%d",&x);
            a[j] += (x << i);  //本行的方案(可能不是合法)
        }
    _init();        //开始优化
    for (int i = 1; i <= tot; i++)         //边界条件
    {
        if (!((st[i] | a[1]) == a[1]))continue;  //是否合法
        f[1][st[i]] = 1;
    }
    for (int i = 2; i <= n; i++)
    {
        for (int j = 1; j <= tot; j++)
        {
            if (!((st[j] | a[i]) == a[i]))continue;   //判断合法
            for (int k = 1; k <= tot; k++)
            {
                if (!((st[k] | a[i - 1]) == a[i - 1]))continue;  //同上条注释
                if (st[j] & st[k]) continue;
                f[i][st[j]] += f[i - 1][st[k]];      //转移
                f[i][st[j]] %= 100000000;
            }
        }
    }
    int ans = 0;
    for (int j = 1; j <= tot; j++)             //答案
        ans += f[n][st[j]], ans %= 100000000;
    printf ("%d", ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/GJY-JURUO/p/12037232.html