AOJ2141 Girls' Party
問題リンク Girls' Party
- 概要
ある整数Nと円形に並んだBチームとGチームの人たちが入力で与えられる。時計回りに数えていき、N人目の人が輪から外れる。輪から外れた次の人から再びN人目が輪から外れる。円がBチームのみ、もしくはGチームのみになるまでこれを繰り返す。また、1度だけN人目ではなくN+1人目の人を輪から外すことができる。入力文字列の最初の人を、初回の数えはじめとする。このとき、Bチームが勝利したときに残っているBチームの人数の最大値を答えよ。
1 <= N <= 2^30
2 <= 人数 <= 200
- 解法
深さ優先探索+枝刈りです。
数えはじめの人を先頭にした文字列によって円の状態が表せます。また、それらについて、N+1人目を抜くやり方を行ったかどうかの状態で更に分かれます。
ある円の状態のN人目(N+1人目)はMODを使うことで一発で計算できます。
- ソース
import java.util.HashSet; import java.util.Scanner; import java.util.Set; //Girls' Party public class AOJ2141 { int N, res; Set<String>[] v; void dfs(int nb, int ng, int z, String s){ if(nb<=res)return; if(ng==0){ res = nb; return; } if(v[z].contains(s))return; v[z].add(s); int n = s.length(), d = (N-1)%n; if(s.charAt(d)=='B'){ dfs(nb-1, ng, z, s.substring(d+1)+s.substring(0, d)); } else{ dfs(nb, ng-1, z, s.substring(d+1)+s.substring(0, d)); } if(z==1)return; d = N%n; if(s.charAt(d)=='B'){ dfs(nb-1, ng, 1, s.substring(d+1)+s.substring(0, d)); } else{ dfs(nb, ng-1, 1, s.substring(d+1)+s.substring(0, d)); } } @SuppressWarnings("unchecked") void run(){ Scanner sc = new Scanner(System.in); int T = sc.nextInt(); while(T--!=0){ N = sc.nextInt(); String s = sc.next(); v = new Set[2]; v[0] = new HashSet<String>(); v[1] = new HashSet<String>(); res = 0; int nb = 0, ng = 0; for(char c:s.toCharArray()) if(c=='B')nb++; else ng++; dfs(nb, ng, 0, s); System.out.println(res); } } public static void main(String[] args) { new AOJ2141().run(); } }