上次我们讲了dfs和bfs,上一道题。
题目描述: 区赛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