2014 Super Training #6 G Trim the Nails --状态压缩+BFS

原题: ZOJ 3675 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3675

由m<=20可知,可用一个二进制数表示指甲的状态,最多2^20,初始状态为0,表示指甲都没剪,然后BFS找解,每次枚举剪刀的两个方向,枚举移动的位数进行扩展状态即可。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
#define N 10007

struct node
{
    int state,step;
    node(int _state,int _step)
    {
        state = _state;
        step = _step;
    }
    node(){}
};

int vis[1<<21];
int cut[2]; //两个方向
queue<node> que;
int n,m;

int bfs(int s)
{
    int i,j,k;
    memset(vis,0,sizeof(vis));
    while(!que.empty())
        que.pop();
    int E = (1<<m)-1;
    que.push(node(s,0));
    vis[s] = 1;
    while(!que.empty())
    {
        node tmp = que.front();
        que.pop();
        int state = tmp.state;
        int step = tmp.step;
        int tms = state;
        for(i=0;i<2;i++) //direction
        {
            for(j=0;j<n;j++)  //move
            {
                int end = ((cut[i]>>j) | tms) & E;  // &E : keep m bit
                if(vis[end])
                    continue;
                vis[end] = 1;
                if(end == E)
                    return step+1;
                que.push(node(end,step+1));
            }
            for(j=0;j<m;j++)
            {
                int to = ((cut[i]<<j) | tms) & E;
                if(vis[to])
                    continue;
                vis[to] = 1;
                if(to == E)
                    return step+1;
                que.push(node(to,step+1));
            }
        }
    }
    return -1;
}

int main()
{
    int i,j;
    char ss[13];
    while(scanf("%d",&n)!=EOF)
    {
        cut[0] = cut[1] = 0;
        scanf("%s",ss);
        for(i=0;i<=n;i++)
        {
            if(ss[i] == ‘*‘)
            {
                cut[0] |= (1<<i);
                cut[1] |= (1<<(n-1-i));
            }
        }
        scanf("%d",&m);
        if(cut[0] == 0)
        {
            puts("-1");
            continue;
        }
        printf("%d\n",bfs(0));
    }
    return 0;
}

2014 Super Training #6 G Trim the Nails --状态压缩+BFS,布布扣,bubuko.com

时间: 2024-10-12 17:02:29

2014 Super Training #6 G Trim the Nails --状态压缩+BFS的相关文章

2014 Super Training #4 G What day is that day? --两种方法

原题: ZOJ 3785 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3785 题意:当天是星期六,问经过1^1+2^2+3^3....+n^n天后是星期几? 这题开始以为是这种式子的求和问题,翻了半天没翻到公式.结果没搞出来.后来发现有两种方法. 第一种方法: 找规律 打表可以看出,这些数的结果出现42一循环,所以直接就处理出前42个,后面的就用前面的. 代码: #include <iostream> #inclu

2014 Super Training #10 G Nostop --矩阵快速幂

原题: FZU 2173 http://acm.fzu.edu.cn/problem.php?pid=2173 一开始看到这个题毫无头绪,根本没想到是矩阵快速幂,其实看见k那么大,就应该想到用快速幂什么的,况且n<=50,可以用矩阵来表示图. 1.为什么能用矩阵快速幂呢? 原理: 原始矩阵m[][]中,m[u][v]代表u到v的花费,求矩阵的k次幂后,此时m[u][v]代表,从u走向b经过v步的最少花费注意此时矩阵的相乘应该写成:m[a][b]=min(m[a][1]+m[1][b],...m[

2014 Super Training #6 F Search in the Wiki --集合取交+暴力

原题: ZOJ 3674 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3674 题意不难理解,很容易想到用暴力,但是无从下手,不知道怎么实现.后来看了网上的代码,直接用vector和map暴力,用到了set_intersection()函数,之前也听过这个函数,但是一直没写过,于是照着他的代码打了一遍,算是见识一下这个函数了. 代码看一下就能看懂了,关键看自己能不能写出来. 代码: #include <iostream

2014 Super Training #9 F A Simple Tree Problem --DFS+线段树

原题: ZOJ 3686 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3686 这题本来是一个比较水的线段树,结果一个mark坑了我好几个小时..哎.太弱. 先DFS这棵树,树形结构转换为线性结构,每个节点有一个第一次遍历的时间和最后一次遍历的时间,之间的时间戳都为子树的时间戳,用线段树更新这段区间即可实现更新子树的效果,用到懒操作节省时间. 坑我的地方: update时,不能写成:tree[rt].mark = 1,

2014 Super Training #4 B Problem Arrangement

原题:ZOJ 3777  http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3777 题意:给每个题目安排在每个位置的value.有一个程序随机选择安排的顺序,总的value值大于等于m时,就可以接受这个安排.问能够获得一次满足条件的安排的期望次数. 这题不会做,看网上是用状态压缩DP做的. 定义: dp[i][j]为选取了前i行,趣味和为j的方案种数. 由于程序是每次随机选择一个排列,每次的选择之间不影响,而且每次选中的概

2014 Super Training #9 E Destroy --树的直径+树形DP

原题: ZOJ 3684 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3684 题意: 给你一棵树,树的根是树的中心(到其他点的最远距离最小).现在你要破坏所有叶子节点到根节点的连通,每条边破坏都需要一定能量.你有一个能量为power的武器,能破坏能量小于等于power的任何路.求最少需要的power. 解法参考博客:http://blog.csdn.net/gzh1992n/article/details/86511

2014 Super Training #10 C Shadow --SPFA/随便搞

原题: FZU 2169 http://acm.fzu.edu.cn/problem.php?pid=2169 这题貌似有两种解法,DFS和SPFA,但是DFS怎么都RE,SPFA也要用邻接表表示边,用向量表示的话会TLE,而且用SPFA有一个异或,就是题目说要沿最短路走到都城,但是SPFA是走最短路去消灭叛军,然后再走回都城,我不知道怎么回事,不知道能不能有大神解释.因为这样的话,有多少叛军就能消灭多少叛军了,那就不要用什么算法 了,直接一个统计.于是试了一下,居然A了,瞬间变成大水题,我无法

2014 Super Training #7 C Diablo III --背包问题(DP)

原题: ZOJ 3769 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3769 一个带有一些限制的背包问题. 假设在没有限制的情况下,那么定义:dp[i][j]表示在前 i 类物品中,总的Toughness为 j 的时候最大的伤害值. 取到第K类的第x个物品时(属性值为D,T),则有转移方程: dp[K][j+T] = max(dp[K][j+T],dp[K-1][j]+D) .其中j+T超过m时按m算就可以了. 但是

2014 Super Training #1 F Passage 概率DP

原题: HDU 3366   http://acm.hdu.edu.cn/showproblem.php?pid=3366 本来用贪心去做,怎么都WA,后来看网上原来是一个DP题. 首先按P/Q来做排序,即P越大,Q越小就越好,这样可以确保先选最优的路走. dp[i][j]表示已经到了第i条路(说明前i-1条都没成功的情况),还剩j块钱时能够走出去的概率. 则方程: dp[i][j] = way[i].P + way[i].Q*(dp[i+1][j-1]) + way[i].D*(dp[i+1]