2010-1089

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

程序解释:
struct node的定义仅仅是为了记录状态方便记忆化搜索;
move(pos, t)表示在大法师中毒还剩的持续时间pos时,t秒后大法师最多能移动多少距离;
主要函数是gao(s0, s1, pos, m, h), 就是返回当大法师位置为s0,warden位置为s1,大法师中毒还剩的持续时间pos,warden魔法值为m,大法师血量为h时,warden是否能成功杀掉大法师。

主要的判断逻辑如下:

1、先判断大法师是否已经成功跑回基地,因为题目说了是要在大法师回到基地前杀掉。

2、在大法师未回到基地的前提下,判断大法师是否已经死亡。

3、在以上的前提下,如果warden能成功地卡大法师位,那么warden以后的最优反应就是不断地放能耗血的1、2招。

4、如果未能卡位,则warden则需要尝试施放1、2、3招或者是什么招都不放,追上大法师。

5、如果以上尝试都未能返回成功,则返回无法杀死大法师。

程序如下:
{{{
#!cpp
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;

int t1, p1, r1, h1;
int t2, p2, r2, h2, T;
int p3, r3;
int v0, v1;

struct node{
    int a, b, c, d, e;
    node(int a, int b, int c, int d, int e):a(a), b(b), c(c), d(d), e(e){}
};
inline bool operator <(const node &p1, const node & p2){
    if (p1.a != p2.a)
        return p1.a < p2.a;
    if (p1.b != p2.b)
        return p1.b < p2.b;
    if (p1.c != p2.c)
        return p1.c < p2.c;
    if (p1.d != p2.d)
        return p1.d < p2.d;  
        return p1.e < p2.e;  
}
map <node, int> ans;
inline int move(int pos, int t){
    int ret = 0;
    while (t--){
        if (pos-- > 0)
            ++ret;
        else
            ret += v0;
    }
    return ret;
}
bool gao(int s0, int s1, int pos, int m, int h){

    pos = max(pos, 0);

    node tmp(s0, s1, pos, m, h);
    if (ans.find(tmp) != ans.end()){
        return ans[tmp];
    }
    int &ret = ans[tmp];    

    if (s0 <= 0)
        return ret = false; 

    if (h <= 0)
        return ret = true;

    int v = pos ? 1 : v0;

    if (s0 > s1){
        if (m >= p1 && gao(s0, s1, --pos, m - p1, h - h1))
            return ret = true;
        if (m >= p2 && gao(s0, s1, --pos, m - p2, h - h2))
            return ret = true;      
    } else {
        if (m >= p1 && r1 >= abs(s1 - (s0 - move(pos, t1))) && gao(s0 - move(pos, t1), s1, pos - t1, m - p1, h - h1))
            return ret = true;
        if (m >= p2 && r2 >= abs(s1 - (s0 - move(pos, t2))) && gao(s0 - move(pos, t2), s1, T, m - p2, h - h2))
            return ret = true;
        if (m >= p3 && gao(s0 - v, max(s1 - r3, s0 - v - 1), --pos, m - p3, h))
            return ret = true;
        if (gao(s0 - v, max(s1 - v1, s0 - v), --pos, m, h))
            return ret = true;
    }   
    return false;
}

int main(){
    int s0, s1, m0, h0;
    scanf("%*d");
    while (scanf("%d%d%d%d%d%d", &s0, &s1, &v0, &v1, &m0, &h0) != EOF){

        scanf("%d%d%d%d", &t1, &p1, &r1, &h1);
        scanf("%d%d%d%d%d", &t2, &p2, &r2, &h2, &T);
        scanf("%d%d", &p3, &r3);

        ans.clear();
        printf("%s\n", gao(s0, s1, 0, m0, h0) ? "yes" : "no");
    }   
    return 0;
}
}}}

程序解释:

struct node的定义仅仅是为了记录状态方便记忆化搜索;

move(pos, t)表示在大法师中毒还剩的持续时间pos时,t秒后大法师最多能移动多少距离;

主要函数是gao(s0, s1, pos, m, h), 就是返回当大法师位置为s0,warden位置为s1,大法师中毒还剩的持续时间pos,warden魔法值为m,大法师血量为h时,warden是否能成功杀掉大法师。

主要的判断逻辑如下:

1、先判断大法师是否已经成功跑回基地,因为题目说了是要在大法师回到基地前杀掉。

2、在大法师未回到基地的前提下,判断大法师是否已经死亡。

3、在以上的前提下,如果warden能成功地卡大法师位,那么warden以后的最优反应就是不断地放能耗血的1、2招。

4、如果未能卡位,则warden则需要尝试施放1、2、3招或者是什么招都不放,追上大法师。

5、如果以上尝试都未能返回成功,则返回无法杀死大法师。

程序如下:

#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
int t1, p1, r1, h1;
int t2, p2, r2, h2, T;
int p3, r3;
int v0, v1;
struct node{
    int a, b, c, d, e;
    node(int a, int b, int c, int d, int e):a(a), b(b), c(c), d(d), e(e){}
};
inline bool operator <(const node &p1, const node & p2){
    if (p1.a != p2.a)
        return p1.a < p2.a;
    if (p1.b != p2.b)
        return p1.b < p2.b;
    if (p1.c != p2.c)
        return p1.c < p2.c;
    if (p1.d != p2.d)
        return p1.d < p2.d;  
        return p1.e < p2.e;  
}
map <node, int> ans;
inline int move(int pos, int t){
    int ret = 0;
    while (t--){
        if (pos-- > 0)
            ++ret;
        else
            ret += v0;
    }
    return ret;
}
bool gao(int s0, int s1, int pos, int m, int h){
    pos = max(pos, 0);
    node tmp(s0, s1, pos, m, h);
    if (ans.find(tmp) != ans.end()){
        return ans[tmp];
    }
    int &ret = ans[tmp];    
    if (s0 <= 0)
        return ret = false; 
    if (h <= 0)
        return ret = true;
    int v = pos ? 1 : v0;
    if (s0 > s1){
        if (m >= p1 && gao(s0, s1, --pos, m - p1, h - h1))
            return ret = true;
        if (m >= p2 && gao(s0, s1, --pos, m - p2, h - h2))
            return ret = true;      
    } else {
        if (m >= p1 && r1 >= abs(s1 - (s0 - move(pos, t1))) && gao(s0 - move(pos, t1), s1, pos - t1, m - p1, h - h1))
            return ret = true;
        if (m >= p2 && r2 >= abs(s1 - (s0 - move(pos, t2))) && gao(s0 - move(pos, t2), s1, T, m - p2, h - h2))
            return ret = true;
        if (m >= p3 && gao(s0 - v, max(s1 - r3, s0 - v - 1), --pos, m - p3, h))
            return ret = true;
        if (gao(s0 - v, max(s1 - v1, s0 - v), --pos, m, h))
            return ret = true;
    }   
    return false;
}
int main(){
    int s0, s1, m0, h0;
    scanf("%*d");
    while (scanf("%d%d%d%d%d%d", &s0, &s1, &v0, &v1, &m0, &h0) != EOF){
        scanf("%d%d%d%d", &t1, &p1, &r1, &h1);
        scanf("%d%d%d%d%d", &t2, &p2, &r2, &h2, &T);
        scanf("%d%d", &p3, &r3);
        ans.clear();
        printf("%s\n", gao(s0, s1, 0, m0, h0) ? "yes" : "no");
    }   
    return 0;
}