题解:ABC319C - False Hope

题解: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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值