链接:Atcoder。
链接:洛谷。
算法难度:B。
思维难度:B。
调码难度:A。
综合评价:普及/提高-。
利用深度优先搜索,找出每一种选取各点的顺序,然后分别按行、列、对角线判断它是否会失望,无论如何方案总数(s)都加一,如果失望了b(记录失望次数)就加一。
答案自然是经过精度处理后的(s-b)/s。
O(1),因为3是常数,但是9!也够了。
输出18位小数就行啦。
- #include
- using namespace std;
- struct Info{
- int td,tn;
- bool operator<(Info ot){
- return 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。