BNU Summer Training 2014.08.26 JZOJ Problem Set - 3675 Trim the Nails

Trim the Nails

Time Limit: 2 Seconds       Memory Limit: 65536 KB

Robert is clipping his fingernails. But the nail clipper is old and the edge of the nail clipper is potholed.

The nail clipper's edge is N millimeters wide. And we use N characters('.' or '*') to represent the potholed nail clipper. '.' represents 1 bad millimeter edge, and '*' represents 1 good millimeter edge.(eg. "*****" is a 5 millimeters nail clipper with the whole edge good. "***..." is a 6 millimeters nail clipper with half of its edge good and half of its edge bad.)

Notice Robert can turn over the clipper. Turning over a "**...*"-nail clipper will make a "*...**"-nail clipper.

One-millimeter good edge will cut down Robert's one-millimeter fingernail. But bad one will not. It will keep the one-millimeter unclipped.

Robert's fingernail is M millimeters wide. How many times at least should Robert cut his fingernail?

Input

There will be multiple test cases(about 15). Please process to the end of input.

First line contains one integer N.(1≤N≤10)

Second line contains N characters only consists of '.' and '*'.

Third line contains one integer M.(1≤M≤20)

Output

One line for each case containing only one integer which is the least number of cuts. If Robert cannot clipper his fingernail then output -1.

Sample Input
8
****..**
4
6
*..***
7
Sample Output
1
2


题意就不解释了

BFS +位运算(状态压缩),把状态用一个数表示

#include<iostream>

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
typedef long long LL;
const int MAX=0xfffffff;
const int mx = 1100000;
int vis[mx],dis[mx];
int x[] = {0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383,
32767, 65535, 131071, 262143, 524287, 1048575, 2097151};//这是长度为i已经剪好的指甲,判断用
int bfs(int up,int down,int n,int m)
{
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    queue<int >Q;
    Q.push(0);
    dis[0]=0,vis[0]=1;
    while(!Q.empty())
    {
        int q=Q.front();Q.pop();
        if(q==x[m])  return dis[q];
        int tt=up;
        for(int i=0;i<2;i++,tt=down)
            for(int j=0;j<=m;j++)
            {
                int tp=tt>>j;
                int p=(tp|q);
                if(!vis[p])
                {
                    dis[p]=dis[q]+1;
                    vis[p]=1;
                    Q.push(p);
                }
            }
    }
    return -1;
}
int main( )
{
    freopen("1.txt","r",stdin);
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        char s[12];
        scanf("%s",s);
        int up=0,down=0;
        for(int i=0;i<n;i++)
            if(s[i]=='*')
            {
                up=up|(1<<(n-i-1));
                down=down|(1<<(i));
            }
        int m;
        scanf("%d",&m);
        if(m>n)  //左对齐
        {
            up=up<<(m-n);
            down<<=(m-n);
        }
        else
        {
            up>>=(n-m);
            down>>=(n-m);
        }
        int ans=bfs(up,down,n,m);
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值