题解:ABC319C - False Hope
·题目
链接:Atcoder。
链接:洛谷。
·难度
算法难度:B。
思维难度:B。
调码难度:A。
综合评价:普及/提高-。
·算法
深度优先搜索。
·思路
利用深度优先搜索,找出每一种选取各点的顺序,然后分别按行、列、对角线判断它是否会失望,无论如何方案总数(s)都加一,如果失望了b(记录失望次数)就加一。
答案自然是经过精度处理后的(s-b)/s。
·代价
O(1),因为3是常数,但是9!也够了。
·细节
输出18位小数就行啦。
·代码
#include<bits/stdc++.h>
using namespace std;
struct Info{
int td,tn;
bool operator<(Info ot){
return td<ot.td;
}
};
Info inf[4]={};
//inf存储的是每次判定的一整行、列、对角线里个点出现的次序和上面的数
int num[4][4]={},q[4][4]={},b=0,s=0;
//num就是点上面的数,q是整体出现次序,b是失望次数,s总次数
bool bl[4][4]={};
//bl就是记录dfs过程中某个点选过与否
inline void dfs(int d);
int main(){
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
cin>>num[i][j];
}
}
//输入
dfs(1);
//dfs入口:开始处理第一个
printf("%.18lf",double(double(s-b)/double(s)));
//输出经过处理的答案
return 0;
}
inline void dfs(int d){
if(d==10){
//都处理完了
s++;
//总次数+1
bool f=false;
//记录不失望
for(int i=1;i<=3;i++){
inf[1]={q[i][1],num[i][1]};
inf[2]={q[i][2],num[i][2]};
inf[3]={q[i][3],num[i][3]};
sort(inf+1,inf+4);
if(inf[1].tn==inf[2].tn){
f=true;
}
}
//每行判断
for(int i=1;i<=3;i++){
inf[1]={q[1][i],num[1][i]};
inf[2]={q[2][i],num[2][i]};
inf[3]={q[3][i],num[3][i]};
sort(inf+1,inf+4);
if(inf[1].tn==inf[2].tn){
f=true;
}
}
//每列判断
inf[1]={q[1][1],num[1][1]};
inf[2]={q[2][2],num[2][2]};
inf[3]={q[3][3],num[3][3]};
sort(inf+1,inf+4);
if(inf[1].tn==inf[2].tn){
f=true;
}
inf[1]={q[1][3],num[1][3]};
inf[2]={q[2][2],num[2][2]};
inf[3]={q[3][1],num[3][1]};
sort(inf+1,inf+4);
if(inf[1].tn==inf[2].tn){
f=true;
}
//对角线判断
if(f==true){
//如果失望了就增加失望总数
b++;
}
}else{
//继续处理
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
if(bl[i][j]==false){
//找到一个没被用过的点
bl[i][j]=true;
q[i][j]=d;
//记录“已被用过”并记录出现次序
dfs(d+1);
//往下跑
bl[i][j]=false;
//回溯
}
}
}
}
}
·注意
精度处理要转为double。