您的位置:首页 > 其它

UVa 321 & ZOJ 1301 - The New Villa

2014-05-25 16:27 351 查看
传送门UVa 321 & ZOJ 1301 - The New Villa



第一次写这么长的代码。。各种艰难。

参考了shuangde800的解题报告。

从他的文章标题可以看出他对这题的深深怨念。。。。

题意是一个青年要从房子的走廊到他自己的房间里去,他不敢去黑暗的房间,幸好每个房间的开关在别的房间里。

给出数据,求他能不能到达卧室并关掉除了卧室之外的灯。

这题的“状态”是每个房间的灯的情况,和人所在的位置,所以只需要记录这个状态。

其他的和八数码差不多。。虽然如此,但是我还是在哈希函数上遇到了困难。。原来依然可以用BKDRHash来解决。。

还有扩展结点的时候的问题。。一开始我只想到循环三次,分别对应出门,关灯,开灯。。可是一个房间可以有很多开关的。。

最后在输出路径那里,只是把昨天那题变一下,加了一个房间编号,我就不会了。。(捂脸



具体的分析[b]shuangde800已经讲很好了,大家参考他的吧。[/b]

终于可以安心写高数作业了╮(╯▽╰)╭





#include <cstdio>
#include <cstring>
using namespace std;
const int HashSize = 2000000;
const int MAXN = 300000;
const char action[][50] = {"- Move to room ", "- Switch off light in room ", "- Switch on light in room "};

typedef int State[11];

State qu[MAXN];
int head[HashSize], next[HashSize];
int room[11][11], swit[11][11], roomNum;
int father[MAXN], ans, step[MAXN];
char path[MAXN][35];

inline void BFS();
inline bool TryToInsert(int s);
inline bool IsOk(State &cur);
inline void Init();
inline bool Go(State &curState, int curLoca, int tarGet, int way);
inline int BKDHash(State &s);
inline void PrintPath(int cur);

int main()
{
//freopen("input.txt", "r", stdin);
int d, s, i, j, a, b, cases = 1;
while (scanf("%d%d%d", &roomNum, &d, &s), roomNum + d + s)
{
memset(room, 0, sizeof(room));
memset(swit, 0, sizeof(swit));
for (i = 0; i < d; i++)
{
scanf("%d%d", &a, &b);
room[a][b] = room[b][a] = 1;
}
for (i = 0; i < s; i++)
{
scanf("%d%d", &a, &b);
swit[a][b] = 1;
}
BFS();
printf("Villa #%d\n", cases++);
if (ans != -1)
{
printf("The problem can be solved in %d steps:\n", step[ans]);
PrintPath(ans);
}
else
printf("The problem cannot be solved.\n");
printf("\n");
}
return 0;
}

inline void BFS()
{
int i, j;
Init();
int front = 0, rear = 1;
while (front < rear)
{
State &curState = qu[front];
if (IsOk(curState))
{
ans = front;
return;
}
int curLoca;
for (i = 1; i <= roomNum; i++)
if (curState[i] == 2)
{
curLoca = i;
break;
}
for (i = 1; i <= roomNum; i++)
{
if (i != curLoca)
{
for (int j = 0; j < 3; j++)
{
State &t = qu[rear];
memcpy(t, curState, sizeof(curState));
if (Go(t, curLoca, i, j))
if (TryToInsert(rear))
{
father[rear] = front;
step[rear] = step[front] + 1;
char str[4];
if (i < 10)
str[0] = i + '0', str[1] = '.', str[2] = 0;
if (i == 10)
str[0] = '1', str[1] = '0', str[2] = '.', str[3] = 0;
strcpy(path[rear], action[j]);
strcat(path[rear], str);
rear++;
}
}
}
}
front++;
}
ans = -1;
}

inline bool TryToInsert(int s)
{
int h = BKDHash(qu[s]);
int u = head[h];
while (u)
{
if (memcmp(qu[u], qu[s], sizeof(qu[h])) == 0)
return 0;
u = next[u];
}
next[s] = head[h];
head[h] = s;
return 1;
}

inline int BKDHash(State &s)
{
int seed = 131;
int Hash = 0;
for (int i = 1; i <= roomNum; i++)
Hash = Hash * seed + s[i];
return (Hash & 0x7FFFFFFF) % HashSize;
}

inline bool IsOk(State &cur)
{
int i;
for (i = 1; i < roomNum; i++)
if (cur[i])
return false;
if (cur[i] == 2)
return true;
return false;
}

inline bool Go(State &curState, int curLoca, int tarGet, int way)
{
if (way == 0)
{
if (room[curLoca][tarGet] && curState[tarGet])
{
curState[tarGet] = 2; curState[curLoca] = 1;
return true;
}
}
else if (way == 1)
{
if (swit[curLoca][tarGet] && curState[tarGet])
{
curState[tarGet] = 0;
return true;
}
}
else if (way = 2)
{
if (swit[curLoca][tarGet] && !curState[tarGet])
{
curState[tarGet] = 1;
return true;
}
}
return false;
}

inline void Init()
{
memset(head, 0, sizeof(head));
memset(qu, 0, sizeof(qu));
qu[0][1] = 2;
father[0] = -1, step[0] = 0;
}

inline void PrintPath(int cur)
{
if (father[cur] != -1)
{
PrintPath(father[cur]);
printf("%s\n", path[cur]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM UVa ZOJ