进阶算法——读写优化

  上次我们讲了dfsbfs,上一道题。

题目描述:
区赛2019第三题
RFdragon非常喜欢玩hearthstone,hearthstone中有一种叫“恐怖的奴隶主”的角色和一种叫“亵渎”的法术。
恐怖的奴隶主的特性是:如果一个奴隶主受到伤害但没有死亡,它就会在它左侧离它最近的位置上召唤一个剩余血量为h[i]的奴隶主,i为奴隶主受到伤害后剩余的血量。场上只有四个随从位,因此如果场上已经有4个奴隶主,或者奴隶主的左侧没有空位,那么就不会召唤新的奴隶主。当一个奴隶主受伤后血量降为0或以下,则奴隶主死亡。亵渎的描述是:对场上所有随从从左到右依次造成1点伤害,如果有随从死亡,则再次施放该法术。
RFdragon发现,在某些情况下,当施放亵渎的时候,游戏会进入死循环。RFdragon希望你帮他判断,在当前的场面下,施放亵渎是否会进入死循环。

输入描述:
第一行一个数n,表示奴隶主的血量上限。
第二行n-1个数描述数组h,分别表示奴隶主受伤后剩余血量为1~n-1时,召唤的新奴隶主的剩余血量。
第三行四个数,分别表示场上四个随从位的奴隶主血量,如果为0则说明这个位置没有奴隶主。

输出描述:
如果会进入死循环,输出yes,否则输出no。

输入样例:
2
1
0 2 0 1

输出样例:
yes

其他说明:
0<h[i]<n<15
点击进入炉石官网,有史以来最好玩的卡牌游戏,没有之一!

   这次我们讲的是读写优化。众所周知,读写字符的速度要比数字快得多,因此,通过将读写数字转换成读写字符,读写速度会快的多。快读的思路是:每次读入一个字符,判断它是不是一个数字字符。如果是,就把结果乘10再加上这个数;如果不是,就返回这个数。值得注意的一点是,如果读入的是一个负数,那么数之前会有一个负号,要特判一下。代码如下:

inline int rd()
{
    int x=0,f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}

  这里的“inline”是内联函数的标志,可以将一个函数声明为内联函数,使这个函数调用的更快。isdigit表示判断一个字符是不是数字字符。

  快写快读相反,每次要输出一个数的第一位。由于不知道一个数有多少位,因此我们每次判断要输出的数是不是大于9,如果大于9,表示它至少有两位,我们再判断这个数除以10是不是大于9,直到它只有一位为止。这个过程可以用递归来实现。注意,这里的负数也要特判,代码如下:

inline void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9) write(x/10);
    putchar(x%10+'0');
    return;
}

  这就是快速读写,你学会了吗?

//答案代码 时间复杂度O(N^2) 
#include<cstdio>
#include<iostream>
using namespace std;
inline int rd()
{
    int x=0,f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
int n,h[24],c[14],p[50635][14],num;
inline void dfs()
{
    bool flag=0;
    for(int i=1;i<=4;i++) if(c[i])
    {
        c[i]--;
        if(c[i]) for(int j=i-1;j>=1;j--) if(!c[j])
        {
            c[j]=h[c[i]];
            break;
        }
        else flag=1;
    }
    for(int i=1;i<=num;i++) if(p[i][1]==c[1]&&p[i][2]==c[2]&&p[i][3]==c[3]&&p[i][4]==c[4])
    {
        printf("yes");
        exit(0);
    }
    num++;
    for(int i=1;i<=4;i++) p[num][i]=c[i];
    if(flag) dfs();
    return;
}
int main()
{
    n=rd();
    for(int i=1;i<n;i++) h[i]=rd();
    for(int i=1;i<=4;i++) c[i]=rd();
    dfs();
    printf("no");
    return 0;
}
//答案代码 时间复杂度O(N*logN) 
#include<cstdio>
#include<iostream>
using namespace std;
inline int rd()
{
    int x=0,f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
int n,h[24],c[14],p[50635],num=1;
inline int hex()
{
    int x=0;
    for(int i=1;i<=4;i++) x=x*16+c[i];
    return x;
}
inline void ef(int x)
{
    int head=1,tail=num,mid;
    while(head<=tail)
    {
        mid=(head+tail)/2;
        if(x<mid) tail=mid-1;
        else if(x>mid) head=mid+1;
        else
        {
            printf("yes");
            exit(0);
        }
    }
    return;
}
inline void dfs()
{
    int x;
    bool flag=0;
    for(int i=1;i<=4;i++) if(c[i])
    {
        c[i]--;
        if(c[i]) for(int j=i-1;j>=1;j--) if(!c[j])
        {
            c[j]=h[c[i]];
            break;
        }
        else flag=1;
    }
    if(!flag)
    {
        printf("no");
        exit(0);
    }
    ef(hex());
    p[++num]=hex();
    for(int i=num;i>1;i--)
    {
        if(p[i]<p[i-1]) swap(p[i],p[i-1]);
        else break;
    }
    return;
}
int main()
{
    n=rd();
    for(int i=1;i<n;i++) h[i]=rd();
    for(int i=1;i<=4;i++) c[i]=rd();
    p[1]=hex();
    dfs();
    return 0;
}

Created by RFdragon

猜你喜欢

转载自www.cnblogs.com/RFdragon/p/10946520.html
今日推荐