题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4490
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 279 Accepted Submission(s): 111
Special Judge
不想再看了,写的想吐了。。。。明天再来说我是怎么一路错过来的。。。。。
不是它不水,是我比它更水!!!!!!
题意:三个机器,换小动物。每种机器有一种操作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;
}