【洛谷 P1879】【[USACO06NOV]玉米田Corn Fields】


题目:

链接

思路:

Q:如何想到是状压DP

A:那是因为(我看了标签\(1 ≤ M ≤ 12; 1 ≤ N ≤ 12\)\(2 ^ {12}\) 不过才。。。(Win7计算器使用中)\(4096\)嘛! 然后如果用状压DP也可以优化时空


确定状态:

\(f_{i,j}\) 表示第\(i\)行的方案(对,方案,这是方案而答案是方案数)是\(j\)(是一个二进制数,用十进制来存储,第\(k\)位是\(1/0\)(二进制)表示\(/\)不选)时的方案数。

确定转移方程:

声明:下面的\(j,k\)都是一个合法的方案

设已经进行到\(i\)行,此时的方案是\(j\),上一行的方案是\(k\)

有一个特殊条件(边界):\(i = 1\)

既然是第一行,那么它的所以合法方案都是正确的,所以边界是:
\[\Large {f_{1,j} = 1}\]

也可以很容易地想到本行的合法方案的方案数是上一行的所有合法方案数,也就是:

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

代码:

声明:那个优化可能并无卵用。。。

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;
}
优质内容筛选与推荐>>
1、简单的上传文件方法!
2、利用ContentControl引用资源
3、【DB2】对两列分组之后判断另外一列是否有重复
4、.Net 2.0实例学习:WebBrowser页面与WinForm交互技巧
5、如何在最新的PHP 7.1.0上安装和运行最新的Magento 2.1.3


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号