UVa 10557 - XYZZY

FILE10557-XYZZY4446
23.50%
817
74.54%

题目链接

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=105&page=show_problem&problem=1498


题目:


The prototypical computer adventure game, first designed by Will Crowther on the PDP-10 in the mid-1970s as an attempt at computer-refereed fantasy gaming, and expanded into a puzzle-oriented game by Don Woods at Stanford in 1976. (Woods had been one of the authors of INTERCAL.) Now better known as Adventure or Colossal Cave Adventure, but the TOPS-10 operating system permitted only six-letter filenames in uppercase. See also vadding, Zork, and Infocom.


It has recently been discovered how to run open-source software on the Y-Crate gaming device. A number of enterprising designers have developedAdvent-style games for deployment on the Y-Crate. Your job is to test a number of these designs to see which are winnable.

Each game consists of a set of up to 100 rooms. One of the rooms is thestartand one of the rooms is thefinish. Each room has anenergy valuebetween -100 and +100. One-way doorways interconnect pairs of rooms.

The player begins in the start room with 100energy points. She may pass through any doorway that connects the room she is in to another room, thus entering the other room. The energy value of this room is added to the player's energy. This process continues until she wins by entering the finish room or dies by running out of energy (or quits in frustration). During her adventure the player may enter the same room several times, receiving its energy each time.

The input consists of several test cases. Each test case begins withn, the number of rooms. The rooms are numbered from 1 (the start room) ton(the finish room). Input for thenrooms follows. The input for each room consists of one or more lines containing:

  • the energy value for roomi
  • the number of doorways leaving roomi
  • a list of the rooms that are reachable by the doorways leaving roomi
The start and finish rooms will always have enery level 0. A line containing -1 follows the last test case.

In one line for each case, output "winnable" if it is possible for the player to win, otherwise output "hopeless".

题目翻译:


背景:典型的电脑冒险游戏,最早出现在1970年代中期的PDP-10电脑(数字设备公司DEC生产的)上,是由Will Crowther设计的。这是一种尝试由电脑裁判的奇幻游戏。1976年在斯坦福大学的Don Woods把它拓展成一个拼图游戏(Don Woods是INTERCAL的作者之一)。现在更出名的是冒险或巨大的洞穴探险游戏。但是PDP-10的操作系统只允许6个大写字母的文件名。更多信息请查询vadding, Zork,和Infocom.


最近人们发现如何在Y-Crate游戏设备上运行开源软件。很多企业的设计师都有部署开发好的Advent-Style风格游戏在Y-Crate上。你的工作就是测试这些设计是否可能获胜的。


每场比赛由一组100个房间组成。其中一个房间是起点,另一个房间是终点。 每个房间有一个能量值 ,从 -100到+ 100。其中有一些只能单向行走的门把这些房间连接起来。


玩家开始时会自动获得100点能量值。 她可以通过单向房间门进入另一个门,并且可以任意重复次数进入一个房间,而且每次进入那个房间都可以获得那个能量值(正的能量值是增加她的能量,负值减少她的能量)。如果在能量用完(变为0或者负数)之前能够走到终点房间,那么就可以赢。否则,就是输。


样例输入:

5
0 1 2
-60 1 3
-60 1 4
20 1 5
0 0
5
0 1 2
20 1 3
-60 1 4
-60 1 5
0 0
5
0 1 2
21 1 3
-60 1 4
-60 1 5
0 0
5
0 1 2
20 2 1 3
-60 1 4
-60 1 5
0 0
-1

样例输出:

hopeless
hopeless
winnable
winnable


分析与总结:

这题首先想到的就是用深搜来做。


仔细分析题目可以看出, 可以重复进入一个房间,也就是可以任意次数来往两个房间。这样的话,这个游戏就有个“BUG”:只要有两个相连的房间(循环的), 例如,其中一个为10, 另一个为-2, 那么便可以反复来玩这两个房间,从而可以获得一个无限大的能量! 这样的话,如果可以找到通往终点的路,由于可以获得无限能量,那么就一定可以赢的!


利用这一点,在进行深搜时,一旦发现可以进入之前走过的房间(即有环图),那么就可以进行判断,是否可以获得无限能量。如果可以获得无限能量的话,就再从当前这点开始搜索,看看能否到达终点,如果可以的话,那么就直接判定为胜利!


在网上搜这题解题报告时,会发现很多都是用什么SPFA做的,其实用DFS+特判就可以了。


AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define INF 2147483646
using namespace std;
int nRoom, energy[105];
struct Node{
    int val;
    int nLeave;
    int reach[105];
};
Node room[105];
bool vis[105], flag; 
int que[100000];

// 这个搜索能获得无限能量的点能不能直接到达终点
void bfs(int pos){
    memset(vis, 0, sizeof(vis));
    vis[pos] = true;
    int front=0, rear=1;
    que[0] = pos;
    while(front < rear){
        int q = que[front++];
        if(q == nRoom){ flag=true; return; }
        for(int i=0; i<room[q].nLeave; ++i){
            int m = room[q].reach[i];
            if(!vis[m] && m>=1 && m<=nRoom) {
                vis[m] = true;
                que[rear++] = m;
            }
        }
    }
}

void dfs(int pos, int val){
    if(flag || pos<=0 || pos>nRoom) return;
 //   printf("Room %d : left = %d\n", pos, val+room[pos].val);
    if(val <= 0) return;
    if(pos==nRoom && val>0) { flag = true; return; }

    for(int i=0; i<room[pos].nLeave; ++i){
        int m=room[pos].reach[i];
        // 如果目标是访问过的,并且这次到目标比上次到目标的能量大
        // 那么可以获得无限能量, 直接搜这个点有没有路径到终点
        if(energy[m] && energy[m]<val+room[m].val) {
            bfs(pos);
            if(flag) return;
        }
        if(!energy[m] && val+room[m].val>0){
            energy[m] = val+room[m].val;
            dfs(m, val+room[m].val);
        }
    }
}

int main(){
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
#endif
    while(~scanf("%d", &nRoom) && nRoom!=-1){
        for(int i=1; i<=nRoom; ++i){
            scanf("%d %d", &room[i].val, &room[i].nLeave);
            for(int j=0; j<room[i].nLeave; ++j)
                scanf("%d", &room[i].reach[j]);
        }

        memset(vis, 0, sizeof(vis));
        memset(energy, 0, sizeof(energy));
        energy[1] = 100;

        flag = false;
        dfs(1, 100);
        if(flag) printf("winnable\n");
        else printf("hopeless\n");
    }
    return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值