hdu 4490 Mad Veterinarian ( BFS+链表记录路径 )

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4490

Mad Veterinarian

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 279    Accepted Submission(s): 111
Special Judge


Problem Description
Mad Veterinarian puzzles have a mad veterinarian, who has developed several machines that can transform an animal into one or more animals and back again. The puzzle is then to determine if it is possible to change one collection of animals into another by applying the machines in some order (forward or reverse). For example:

Machine A turns one ant into one beaver.
Machine B turns one beaver into one ant, one beaver and one cougar.
Machine C turns one cougar into one ant and one beaver.

Can we convert a beaver and a cougar into 3 ants?


Can we convert one ant into 2 ants? NO

These puzzles have the properties that:

1. In forward mode, each machine converts one animal of a given species into a finite, non-empty collection of animals from the species in the puzzle.
2. Each machine can operate in reverse.
3. There is one machine for each species in the puzzle and that machine (in forward mode) takes as input one animal of that species.

Write a program to find the shortest solution (if any) to Mad Veterinarian puzzles. For this problem we will restrict to Mad Veterinarian puzzles with exactly three machines, A, B, C.


 

Input
The first line of input contains a single integer P, (1<= P <= 1000 ), which is the number of data sets that follow. Each data set consists of several lines of input. Each data set should be processed identically and independently.

The first line of each data set consists of two decimal integers separated by a single space. The first integer is the data set number. The second integer is the number, N, of puzzle questions. The next three input lines contain the descriptions of machines A, B and C in that order. Each machine description line consists of three decimal integers separated by spaces giving the number of animals of type a, b and c output for one input animal. The following N lines give the puzzle questions for the Mad Veterinarian puzzle. Each contains seven decimal digits separated by single spaces: the puzzle number, the three starting animal counts for animals a, b and c followed by the three desired ending animal counts for animals a, b and c.


 

Output
For each input data set there are multiple lines of output. The first line of output for each data set contains the data set number, a space and the number of puzzle questions (N). For each puzzle question, there is one line of output which consists of the puzzle question number followed by a space, followed by “NO SOLUTION”, (without the quotes) if there is no solution OR the puzzle question number followed by the shortest number of machine steps used, a space and a sequence of letters [A B C a b c] with capital letters indicating applying the machine in the forward direction and lower case letters indicating applying the machine in the reverse direction.


 

Sample Input
 
   
2 1 2 0 1 0 1 1 1 1 1 0 1 0 1 1 3 0 0 2 1 0 0 2 0 0 2 2 0 3 4 0 0 5 0 0 3 1 2 0 0 0 0 5 2 2 0 0 0 0 4


 

Sample Output
 
   
1 2 1 3 Caa 2 NO SOLUTION 2 2 1 NO SOLUTION 2 25 AcBcccBccBcccAccBccBcccBc


 

Source
Greater New York 2012


 

Recommend
liuyiding

 

不想再看了,写的想吐了。。。。明天再来说我是怎么一路错过来的。。。。。

不是它不水,是我比它更水!!!!!!


题意:三个机器,换小动物。每种机器有一种操作A、B、C。也可以对小动物实现A、B、C的逆操作abc。给定初状态和末状态,问能不能通过6种操作从初状态达到

            末状态。

分析:很裸的BFS+记录路径。

感想:

好多写错和想错的位置-------------

1、致命的错误是:没有先判断能不能换,而是直接录入A、B、C三种操作然后对应的-1,这样处理成辅助数组了以后搜。但是这样是不行的,比如:C操作是0 0 2,

      如果按我之前的做法,当z为0的时候可以变成1,但是没有小动物,怎么能无中生有呢。自然界都没这种神奇的事发生呢!所以错,要先判断,再相应的减去消耗

      的小动物。

2、乱使用宏定义。开始把abcABC定义成宏,而末状态什么的又用ea、eb、ec记录。这样很危险的,因为宏就是直接替代呀,ea eb  ec不就成了 e1 e2 e3。难怪调试

      时发现末状态突然就变了,但是我又没有语句去改它。

3、链表指针混乱了,导致死循环。我对链表和内存的理解真的是太浅薄了。我开始只开了state cur,next。最后每次只是改了cur对应内存的数值,每次都把指针指向cur

      这一个内存空间,最后输出的时候就总输出a停不下来。现在想想,那还叫链表么。后来改成了开个大数组 state snode[100000],在队列里放state的指针。用遍历

      指针每次从队列里取一个指针出来。然后得到新状态在把状态存到snode数组里,相应的地址存进队列。

4、我开始犯了个很BT的错误,为什么以为只要大于-1就可以了,小于-1就continue。改的太久了,忘了最初怎么想的。总之后来next.a什么我以为可以是-1,最后因为

      next.a什么的是vis[][][]判重数组的下标,导致数组越界了。

5、其实可以用set判重,当下标可能为负的时候,还有当数据很大很大的时候,vis根本控制不了。比如这题:要不是因为10意外的数据都可以不要了,用if。。continue

      掉,vis数组是根本控制不了的。(set判重比vis判重慢 )

6、这题据说hdu oj 的数组很小,直接打表就能过的。其实这题还可以用位运算写,因为状态最多只有12 (只针对这题),用个整形的int ,前24位记录aa  bb  cc三个数,另外

      8位记录选择的路径。加减的话就是在整形的移位。


 

代码:

#include
#include
#include
#include

using namespace std;

struct f
{
    int x;
    int y;
    int z;
}ff[3];
struct state
{
    int aa;
    int bb;
    int cc;
    char step;
    state *pre;
}s;
int ea,eb,ec;
char solve[1100];
bool vis[12][12][12];
int rear;
struct state snode[100000];

bool bfs()
{
    int r=0;
    queue q;
    while(!q.empty())
        q.pop();
    s.pre=NULL;
    q.push(&s);
	
	vis[s.aa][s.bb][s.cc]=true;
    while(!q.empty())
    {
        struct state *pNow =q.front();
        q.pop();
        if(pNow->aa==ea && pNow->bb==eb && pNow->cc==ec)
        {
		    rear = 0;
            //state *head;
            for(;pNow!=NULL;pNow=pNow->pre)
            {
                solve[rear++]=pNow->step;
            }
			solve[rear] = '\0';
            return true;
        }
        for(int i=0;i<3;i++)
        {
		
			if (i == 0 && pNow->aa < 1 || i == 1 && pNow->bb < 1 || i == 2 && pNow->cc < 1)
				continue; //条件不满足
            snode[r].aa=pNow->aa+ff[i].x; 
            snode[r].bb=pNow->bb+ff[i].y;
            snode[r].cc=pNow->cc+ff[i].z;
			
			//消耗掉的动物
			if (i == 0) --snode[r].aa; 
			else if (i == 1) --snode[r].bb;
			else --snode[r].cc;

            if(snode[r].aa>10 || snode[r].bb>10 || snode[r].cc>10) continue;
			
            if(vis[snode[r].aa][snode[r].bb][snode[r].cc]==false)
            {
                snode[r].step='A' + i;
                snode[r].pre=pNow;
                q.push(&snode[r]);
                vis[snode[r].aa][snode[r].bb][snode[r].cc]=true;
                ++r; 
            }
        }
		
		//逆序
		for (int i = 0; i < 3; ++i)
		{
			if (pNow->bb < ff[i].y || pNow->cc < ff[i].z || pNow->aa < ff[i].x)
				continue; //条件不满足
		    snode[r].aa=pNow->aa-ff[i].x; 
            snode[r].bb=pNow->bb-ff[i].y;
            snode[r].cc=pNow->cc-ff[i].z;
			
			//增加的动物
			if (i == 0) ++snode[r].aa; 
			else if (i == 1) ++snode[r].bb;
			else ++snode[r].cc;

            if(snode[r].aa>10 || snode[r].bb>10 || snode[r].cc>10) continue;
			
            if(vis[snode[r].aa][snode[r].bb][snode[r].cc]==false)
            {
                snode[r].step='a' + i;
                snode[r].pre=pNow;
                q.push(&snode[r]);
                vis[snode[r].aa][snode[r].bb][snode[r].cc]=true;
                ++r; 
            }
		}
    }
    return false;
}

int main()
{
    int t,i,t1,t2,t3,cs,cas,fuc,j,d;
    scanf("%d",&t);
    while(t--)
    {
        memset(ff,0,sizeof(ff));
        scanf("%d%d",&cas,&fuc);
        for(i=0;i<3;i++)
        {
            scanf("%d%d%d",&t1,&t2,&t3);
            ff[i].x=t1;
            ff[i].y=t2;
            ff[i].z=t3;
        }
		
        printf("%d %d\n",cas,fuc);
        for(d=0;d 0) printf(" ");
				for (int len = strlen(solve) - 1; len >= 0; --len)
                   printf("%c", solve[len]);		
                printf("\n");				   
            }
            else printf("%d NO SOLUTION\n",cs);
        }
    }
    return 0;
}


 

你可能感兴趣的:(搜索)