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
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.
题意:一个人在剪指甲,指甲宽度为m,有一个指甲钳,指甲钳宽度为n,指甲钳的每一个宽度单位有的是坏的,有的是好的,只有好的一个宽度的指甲钳才能剪去一个宽度的指甲。问剪完这m个宽度的指甲需要多少时间。
思路:状态压缩。把每一次剪完后的指甲的看成一个状态。用01串来表示,若有m个1,则说明剪指甲已完成。
AC代码:
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N=1<<21;
int ok[21],dis[N];
bool vis[N];
int n,m;
int clipper1,clipper2;
void init()
{
ok[0]=0; //数组ok保存长度为m的指甲完全剪好的状态
for(int i=1; i<=20; i++)
ok[i]=ok[i-1]<<1|1;
}
int bfs()
{
queue<int> Q;
int cur,next,temp;
memset(vis,false,sizeof(vis));
memset(dis,0,sizeof(dis));
vis[0]=true;
Q.push(0);
while(!Q.empty())
{
cur=Q.front();
Q.pop();
temp=clipper1;
for(int i=0; i<n; i++)
{
temp>>=1; //移动指甲钳
next=temp|cur;
next&=((1<<m)-1);
if(!vis[next])
{
dis[next]=dis[cur]+1;
if(next==ok[m]) return dis[next];
vis[next]=true;
Q.push(next);
}
}
temp=clipper2;
for(int i=0; i<n; i++)
{
temp>>=1;
next=temp|cur;
next&=((1<<m)-1);
if(!vis[next])
{
dis[next]=dis[cur]+1;
if(next==ok[m]) return dis[next];
vis[next]=true;
Q.push(next);
}
}
}
return -1;
}
int main()
{
//freopen("1.txt","r",stdin);
char s[25];
init();
while(scanf("%d",&n)!=EOF)
{
scanf("%s",s);
scanf("%d",&m);
clipper1=0;
clipper2=0;
for(int i=0; i<n; i++)
{
if(s[i]=='*')
clipper1|=(1<<i);
if(s[n-i-1]=='*')
clipper2|=(1<<i);
}
clipper1<<=(m+1);
clipper2<<=(m+1);
n+=m; //指甲钳能移动的长度为n+m
printf("%d\n",bfs());
}
return 0;
}