当前位置:编程学习 > C/C++ >>

HDU 3220Alice’s Cube(按位压缩+BFS)

Alice’s Cube
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1520    Accepted Submission(s): 455
 
 
Problem Description
 
Alice has received a hypercube toy as her birthday present. This hypercube has 16 vertices, numbered from 1 to 16, as illustrated below. On every vertex, there is a light bulb that can be turned on or off. Initially, eight of the light bulbs are turned on and the other eight are turned off. You are allowed to switch the states of two adjacent light bulbs with different states (“on” to “off”, and “off” to “on”; specifically, swap their states) in one operation.
 
Given the initial state of the lights, your task is to calculate the minimum number of steps needed to achieve the target state, in which the light bulbs on the sub cube (1,2,3,4)-(5,6,7,8) are turned off, and the rest of them are turned on.
 
 
Input
There are multiple test cases. The first line of the input contains an integer T, meaning the number of the test cases. There are about 13000 test cases in total.
For each test case there are 16 numbers in a single line, the i-th number is 1 meaning the light of the i-th vertex on the picture is on, and otherwise it’s off.
 
 
Output
For every test cases output a number with case number meaning the minimum steps needed to achieve the goal. If the number is larger than 3, you should output “more”.
 
 
Sample Input
3
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 1 0 0 0 0 0 0 1 0 1 1 1 1 1 1
0 0 0 0 0 0 1 0 1 0 1 1 1 1 1 1
 
 
Sample Output
Case #1: 0
Case #2: 1
Case #3: more
 
 
Source
2009 Asia Shanghai Regional Contest Host by DHU
 
 
 
题目大意:上面有一副图,顶点 有16个灯泡,每个灯泡亮1或者不亮0,我们可以转换灯泡的亮的情况,两个相邻的顶点如果状态不一样可以两个互换状态。初始状态为0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1,然后给你任意一个终止状态,三步以内可以到达,就输出最短步数,否则输出more。
 
      解题思路:每次搜索大概时间复杂度为32^3,然后再加上10^4组测试数据,感觉应该可以直接暴搜。但是要把状态全部都存储下来,估算一下是32^3*16,每次找状态的话是一个一个匹配,那么时间就是10^4*32*3,这样下来时间很悬。于是想到了上次打dafashi的一个位压缩加速的题目,可以用一个int保存所有的0 1 状态,这样直接就开2^16的数组即可,时间上打表之后查询就是O(1)的操作了!
 
      题目地址:Alice’s Cube
 
AC代码:
 
#include<iostream>  
#include<cstdio>  
#include<cmath>  
#include<cstring>  
#include<string>  
#include<queue>  
using namespace std;  
const int maxn=1<<16;  
  
int visi[maxn];  
//两点相连,一共有32条边  
int a[32][2]={{1,2},{3,4},{5,6},{7,8},{9,10},{11,12},{13,14},{15,16},{1,3},{2,4},{5,7},{6,8},{9,11},{10,12},{13,15},{14,16},  
       {1,5},{2,6},{3,7},{4,8},{9,13},{10,14},{11,15},{12,16},{1,9},{2,10},{3,11},{4,12},{5,13},{6,14},{7,15},{8,16}};  
  
void BFS(int p)  
{  
    int i;  
    visi[p]=0;  
    queue <int> mq;  
    mq.push(p);  
    while(!mq.empty())  
    {  
        int t=mq.front();  
        mq.pop();  
        if(visi[t]>=3)  continue;  
        for(i=0;i<32;i++)   //看下可以改变哪两个点  
        {  
            int p1,p2;  
            //表示a[i]灯的状态  
            p1=t&(1<<(a[i][0]-1));  
            p2=t&(1<<(a[i][1]-1));  
            if(p1==p2) continue;  //两个灯状态一样  
            p1=t^(1<<(a[i][0]-1));  
            p2=p1^(1<<(a[i][1]-1));  //两个灯交换状态  
            if(visi[p2]==-1)  //如果是其它的值,说明此时步骤不是最小的  
            {  
                mq.push(p2);  
                visi[p2]=visi[t]+1;  
            }  
        }  
    }  
}  
  
int main()  
{  
    int tes;  
    int x,i,j;  
    x=(1<<16)-(1<<8);   //就是最终状态作为起始状态  
    memset(visi,-1,sizeof(visi));  
    BFS(x);  
    scanf("%d",&tes);  
    for(i=1;i<=tes;i++)  
    {  
        int sum=0;   //表示状态  
        for(j=0;j<16;j++)  
        {  
            int tmp;  
            scanf("%d",&tmp);  
            if(tmp==1)  
                sum+=1<<j;  
        }  
  
        printf("Case #%d: ",i);  
        if(visi[sum]==-1)   //表示三步之内没达到  
            puts("more");  
        else printf("%d\n",visi[sum]);  
    }  
    return 0;  
}  
  
/* 
3 
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
0 1 0 0 0 0 0 0 1 0 1 1 1 1 1 1 
0 0 0 0 0 0 1 0 1 0 1 1 1 1 1 1 
*/  
  

 

 
//31MS  
 
补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,