ZOJ 3675 Trim the Nails(bfs+位运算处理)

来源:互联网 发布:2012sql维护计划 编辑:程序博客网 时间:2024/06/05 00:25
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****..**46*..***7

Sample Output

12

Hint

We use '-' to present the fingernail.For sample 1:fingernail:----nail clipper:****..**Requires one cut.For sample 2:fingernail:-------nail clipper:*..***nail clipper turned over: ***..*Requires two cuts.

Author: YANG, Jueji

Contest: ZOJ Monthly, November 2012


题意:给出一把指甲剪,.代表是坏的,*代表好的,然后给出指甲的长度,问最少多少次修剪才能剪完(指甲剪可以正反2用)

题解:将指甲剪转换成一个数字,0代表好的,1代表没有东西的和坏的,指甲初始为m长度全1的数字,这样他们的&运算就相当于剪指甲了,然后用bfs搜索一下,第一个变成0的就是最好的次数了


#include<stdio.h>#include<string.h>int n,m,mark[2333333];char temp[25],s[25];int pos,neg;struct point{    int cou,data;}p,que[3333333];int bfs(){    int temp=0,sta=0,fin=0;    int i,now1,now2,cou;    memset(mark,0,sizeof(mark));    for(i=0;i<m;i++) temp=temp|(1<<i);  //指甲化成m长度全1的数组    p.cou=0,p.data=temp;  //cou代表次数,data代表现状    mark[temp]=1; //标记,只入队一次    que[fin++]=p;  //数组模拟队列,进行bfs    while(1)    {        p=que[sta++];        if(!p.data) return p.cou;  //若为0,则剪好了,返回次数        now1=p.data&pos; //正着剪        now2=p.data&neg; //反着剪        while((now1&1)==0&&now1) now1=now1>>1;  //将最右端剪好的去掉,贪心策略        while((now2&1)==0&&now2) now2=now2>>1;        cou=p.cou;        if(!mark[now1]) //只入队一次        {            mark[now1]=1;            p.data=now1;            p.cou=cou+1;            que[fin++]=p;        }        if(!mark[now2])        {            mark[now2]=1;            p.data=now2;            p.cou=cou+1;            que[fin++]=p;        }    }}int main(){    int i,j,k,res;    while(scanf("%d%s%d",&n,s,&m)>0)    {        for(i=0;i<n;i++) if(s[i]=='*') break;        if(i>=n){ printf("-1\n"); continue; }        for(j=n-1;j>=i;j--) if(s[j]=='*') break;        for(k=i;k<=j;k++) s[k-i]=s[k];        s[k]='\0';  n=j-i+1;        //这里将指甲剪2端坏的部分去掉,因为必定没有用了,若全部坏掉则输出-1        for(pos=neg=i=0,j=n-1;i<n;i++,j--)        {            if(s[i]=='*') pos=(pos<<1)+1;            else pos=pos<<1;            if(s[j]=='*') neg=(neg<<1)+1;            else neg=neg<<1;        }        pos=~pos,neg=~neg;        //这里将指甲剪化成0和1表示,注意没有东西的和坏的都是1,好的才是0        res=bfs();        printf("%d\n",res);    }    return 0;}


原创粉丝点击