Trim the Nails (DFS+状态压缩) #by Plato

Trim the Nails DFS+状态压缩)

几星期前一次组队赛的题了,今天下午就找了这道题来补了,顺便学习了下状态压缩和位运算的一些知识了。。

思路:看题就知道是DFS了,但是状态的表示需要压缩。

具体,初始状态0000011111(M个1),目标状态0000000(全零)

指甲刀也可以用一个压缩的整数met来表示,0表示good,1表示bad。这样剪一次指甲后的状态就是status&met。

 

其他的还有些细节要注意:

1.   答案为-1的情况,指甲刀全为bad;

2.   指甲刀可以正反使用;

3.   两个简化措施:将met两端的bad去掉,每次剪完将status最末端的0去掉;

4.   只有一个为good的情况可以直接输出答案,优化时间。

 

代码到是挺简洁的,不过写起来还是蛮麻烦的,可能与刚接触状态压缩有关吧~

 

#include <cstdio>
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#define OP(s) cout<<#s<<"="<<s<<" ";
#define PP(s) cout<<#s<<"="<<s<<endl;
using namespace std;

int met1,met2,ans;

void DFS(int dep,int status)
{
    if (status == 0)
    {
        if (dep < ans) ans = dep;
        return;
    }

    while (!(status&1)) status = status>>1;//!wrong status^1 这里是要取最后一位的值,并判断其0or1
    DFS(dep+1,status&met1);
    DFS(dep+1,status&met2);
}

int main()
{
    freopen("test.txt","r",stdin);
    int N,M;
    while (~scanf("%d",&N))
    {
		char str[100];
        scanf("%s",&str[1]);
        met1 = met2 = ~0;
        int num = 0;
        for (int i = 1;i <= N;i++)
            if (str[i] == '*')
            {
                num++;
                met1 = met1&~(1<<i-1);
                met2 = met2&~(1<<N-i);
            }
        if (num) while (met1&1) met1 = met1>>1;
        if (num) while (met2&1) met2 = met2>>1;
        scanf("%d",&M);

        if (!num)
        {
            printf("-1\n");
            continue;
        }
        if (num == 1)
        {
            printf("%d\n",M);
            continue;
        }
        ans = 1<<30;
        int S = ~(~0<<M);
        DFS(0,S);

        printf("%d\n",ans);
    }

    return 0;
}
/*
先去补充了下位运算和状态压缩的一些知识,然后再去写了。
主要有两个错误:
1.首先是查看压缩状态的方法不对
正确的是这样子,for (int i = 15;i >= 1;i--) if (status>>i-1 & 1) cout<<1;else cout<<0;cout<<endl;
2.判断第X位是什么写错了
while (!(status&1)) status = status>>1;
*/


 


你可能感兴趣的:(Trim the Nails (DFS+状态压缩) #by Plato)