D - Deductive Snooker Scoring
[https://qoj.ac/contest/2567/problem/14709]
题意:
斯诺克台球,给出最后的选手A和选手B的得分,以及最后到谁打了,构造一个合法操作序列使得最后结果为给出结果
思路:
记忆化搜索:f[i][j][lft][k][op] 表示 选手A得分为i,选手B得分为j,剩下的球的总数为lft,到选手k打了,比赛阶段(第一阶段打红球,第二阶段打彩球且放回,第三阶段清台)
发现不需要知道红球多少个,彩球多少个才能知道比赛进行的阶段,因为一定是红球先打完。所以剩下来的球小于等于6个时,一定进入清台阶段
int a,b,n,p;
string f[202][202][22][2][3];
//op:0 1 2
//三个阶段
//A:选手A得分
//B:选手B得分
//lft:当前剩余的球的总数
//k:当前击球的选手
//op:阶段
//s:字符串
void dfs(int A,int B,int lft,int k,int op,string s){
if(f[A][B][lft][k][op].size())return ;
f[A][B][lft][k][op]=s;
if(!lft)return;
if(op==0){
if(k==0)dfs(A+1,B,lft-1,k,op+1,s+'1');//选手A进入第二阶段
else dfs(A,B+1,lft-1,k,op+1,s+'1');//选手B进入第二阶段
// dfs(A,B,lft,k^1,op,s+'/');//第一阶段没打进
}
if(op==1){
for(int i=7;i>=2;i--){
//枚举彩球
if(k==0)dfs(A+i,B,lft,k,lft>=7?0:2,s+(char)('0'+i));
else dfs(A,B+i,lft,k,lft>=7?0:2,s+(char)('0'+i));
}
// dfs(A,B,lft,k^1,op-1,s+'/');//第二阶段没打进
}
if(op==2){
if(k==0)dfs(A+8-lft,B,lft-1,k,op,s+(char)('0'+(8-lft)));
else dfs(A,B+8-lft,lft-1,k,op,s+(char)('0'+(8-lft)));
// dfs(A,B,lft,k^1,op,s+'/');
}
dfs(A,B,lft,k^1,lft>=7?0:2,s+'/');
}
void solve(){
cin>>a>>b>>n>>p;
if(a==0&&b==0&&n==21&&p==0){
cout<<endl;return;
}
for(int i=0;i<=2;i++){
if(f[a][b][n][p][i].size()){
cout<<f[a][b][n][p][i]<<endl;return;
}
}
cout<<"NA"<<endl;
}
signed main()
{
ios::sync_with_stdio(false),cin.tie(0);
int T=1;
cin>>T;
dfs(0,0,21,0,0,"");
while(T--){
solve();
}
return 0;
}

浙公网安备 33010602011771号