UVALive - 8144 Sacred Scarecrows DP + FMT 未解决

标签: 数学 FMT
5人阅读 评论(0) 收藏 举报
分类:

简略题意:RC的庄稼地,有些地方已经种了庄稼了。现在需要放置一些稻草人,使得满足以下两个条件:
1. 所有行都包含稻草人。
2. 相邻的两列至少包含两个稻草人。

这题目前还没有AC,但是值得记录。

注意到行很少,因此可以状压进行DP
dp[i][0/1][j]代表,前i列的稻草人存放了那些行,当前列是否有稻草人。

代表集合并卷积,那么转移有如下:
1.dp[i][0]=dp[i1][1]g[0]
2.dp[i][1]=dp[i1][0]g/g[0]+dp[i1][0]g/g[0]=(dp[i1][0]+dp[i1][1])g/g[0]
障碍物的处理直接把对应卷上的g给置零即可,所以可以用FMT来优化到R(2R)C
经过用assert得出测试数据至少有20组…上述算法无法通过。

qls给出了如下解法:
对行容斥,可以知道每列有多少空地,然后 O(c)dp.
容斥用 dfs 枚举集合可以 2r,可以做到 O(2RC).
暂时还没太理解,先想一想。

#define others
#ifdef poj
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
#define eps 1e-8
const double pi = acos(-1.0);

typedef long long LL;
typedef unsigned long long ULL;
void umax(int &a, int b) {
    a = max(a, b);
}
void umin(int &a, int b) {
    a = min(a, b);
}
int dcmp(double x) {
    return fabs(x) <= eps?0:(x > 0?1:-1);
}
void file() {
    freopen("data_in.txt", "r", stdin);
    freopen("data_out.txt", "w", stdout);
}

const LL mod = 1e9+7;

int r, c, lim;
LL dp[2][2][20000], f[20000], g[20000], h[20000];
char G[16][1100];

LL add(LL a, LL b) {
    a += b;
    if(a >= mod) a -= mod;
    return a;
}

LL mul(LL a, LL b) {
    LL sum = 1ll * a * b;
    if(sum >= mod) a %= mod;
    return sum;
}

LL sub(LL a, LL b) {
    a -= b;
    if(a < 0) a += mod;
    return a;
}

void FMT(int col, int on) {
    for(int i = 0; i < lim; i++) g[i] = 0;
    if(on) {
        for(int i = 1; i < lim; i++) {
            bool isok = 1;
            for(int j = 0; j < r; j++) {
                if((i & (1 << j)) && G[j][col] == 'v') isok = 0;
            }
            if(isok) g[i] = 1;
        }
    } else {
        g[0] = 1;
    }
    for(int i = 0; i < r; i++)
        for(int j = 0; j < lim; j++)
            if((j >> i) & 1)
                f[j] = add(f[j], f[j^(1<<i)]);
    for(int i = 0; i < r; i++)
        for(int j = 0; j < lim; j++)
            if((j >> i) & 1)
                g[j] = add(g[j], g[j^(1<<i)]);
    for(int i = 0; i < lim; i++)
        h[i] = mul(f[i], g[i]);
    for(int i = 0; i < r; i++)
        for(int j = 0; j < lim; j++)
            if((j>>i)&1)
                h[j] = sub(h[j], h[j^(1<<i)]);
}

void cpy(LL x[], LL y[]) {
    for(int i = 0; i < lim; i++)
        x[i] = y[i];
}

int main() {
//    file();
int ff = 0;
    while(~scanf("%d%d", &r, &c)) {
        ff++;
//    assert(ff <= 30);
        lim = 1 << r;
        for(int i = 0; i < r; i++)
            for(int j = 1; j <= c; j++)
                scanf(" %c", &G[i][j]);
        for(int i = 0; i < 2; i++)
            for(int j = 0; j < 2; j++)
                for(int k = 0; k < lim; k++) dp[i][j][k] = 0;
        LL ans = 0;
        dp[0][1][0] = 1;
        for(int i = 1; i <= c; i++) {
            int now = i & 1, pre = now ^ 1;
            for(int j = 0; j < lim; j++) dp[now][0][j] = dp[now][1][j] = 0;
            for(int j = 0; j < lim; j++)
                dp[now][0][j] = dp[pre][1][j], dp[pre][1][j] = add(dp[pre][1][j], dp[pre][0][j]);

            cpy(f, dp[pre][1]);
            FMT(i, 1);
            cpy(dp[now][1], h);
        }
        cout<<(dp[c&1][0][(1<<r)-1] + dp[c&1][1][(1<<r)-1])%mod<<'\n';
    }
    return 0;
}
查看评论

UVALive 3983(单调队列优化dp)

链接:点击打开链接 题意:有n个垃圾,第i个垃圾坐标为(xi,yi),重量为wi,有一个机器人,要按照编号从小到大的顺序剑气所有的垃圾兵扔进垃圾桶,垃圾桶在源点,每次总重量不能超过C,两点间距离为曼...
  • stay_accept
  • stay_accept
  • 2016-11-20 16:00:55
  • 329

uvalive4945(dp,贪心)

转自别人http://blog.csdn.net/shuangde800/article/details/10019951 题目大意: Petra和Jan分n个糖果,每个人轮流拿,一次只能拿一个,...
  • vv494049661
  • vv494049661
  • 2016-04-21 19:49:36
  • 263

uvalive3516(DP)

题意: 给出一种遍历多叉树的方式,就是总是向左,左走不同往回走,然后向右,遍历完整棵树,并回到原点; 图上五棵树的遍历结果都是ABABABA; 现在给出一个字符串,问能表示几棵树; ...
  • yeyeyeguoguo
  • yeyeyeguoguo
  • 2015-07-22 21:47:31
  • 368

uvalive 3942(dp + trie)

题意:有一个长字符串,然后给出了n个不同的单词,问长字符串是由这些单词构成的不同方案有几种。 题解:明显是dp,f[i]表示从字符i开始有多少种方案,f[i] = sum{f[i + len(x)},...
  • u013392752
  • u013392752
  • 2015-04-09 00:07:45
  • 433

UVALive 3942(使用数据结构trie树加速dp)

题意:给定一个长度不超过30000的字符串str,然后给定n(n 题解:这里dp[i]表示从i到字符串尾len有dp[i]种方案,那么前一种的转态dp[i+1]的组合数是由(dp[i],i+1)这...
  • qq_24489717
  • qq_24489717
  • 2016-03-09 00:54:44
  • 469

UVALive4987(dp+贪心)

链接:点击打开链接 题意:在一条直线上有n个施工队和m个避难所,给出每个施工队和避难所相对于原点的距离,求在保证每个避难点有一个施工队的前提下,所有施工队移动的最小距离和 代码:#include #...
  • stay_accept
  • stay_accept
  • 2016-08-22 18:12:13
  • 221

uvalive4625(dp + 二分)

题目大意: 给你一串 n 个数,表示n个球,给你这n个球的重量,要你把这n个数分成 m - 1 段,每段的数字个数都是偶数,对于每一段,它的半段数字个数都不超过d,找出一种分发,使所有的这些半段的重...
  • vv494049661
  • vv494049661
  • 2016-04-27 15:07:49
  • 348

UVaLive LA 4256 | UVa 1424 - Salesmen(简单DP)

Salesmen Time Limit:3000MS   Memory Limit:Unknown   64bit IO Format:%lld & %llu ...
  • zhaosdfa
  • zhaosdfa
  • 2014-07-27 15:31:03
  • 566

uvalive4490(状态压缩 + dp)

题目大意: 从左到右给出n本数的高度和最多可以抽取的书本的数量k,如果书本与相邻的书本的高度不相同的话就是一个段,段越多混乱度就越高。求最低的混乱度。思路: dp[i][j][s][end]表示前...
  • vv494049661
  • vv494049661
  • 2016-04-26 22:21:23
  • 277

uvalive 3942 Remember the Word 字典树+dp

代码:
  • a601025382s
  • a601025382s
  • 2014-08-08 12:38:24
  • 877
    个人资料
    持之以恒
    等级:
    访问量: 1万+
    积分: 1250
    排名: 4万+
    最新评论
    友情链接