• 洛谷P1074 靶形数独【dfs】【剪枝】


    题目https://www.luogu.org/problemnew/show/P1074

    题意:

    数独的分数如下。一个数独的总分数就是权值乘所填数字之和。

    现在给一个未完成的数独,问分数最高的数独的总分。

    思路:

    感觉dfs就是要学会各种剪枝。要敢于剪枝。

    最基本的思路就是记下要填的位置和每行每列每个方块填数的情况,然后每个空格都1~9试过来。填完了计算分数。

    但是如果仅仅是这样的话还是不行,只有75分TLE。

    我们做数独的时候一般都是找零最少的某行某列或某个方格开始填,因为这样的可能性比较少。

    这道题也应该考虑到这样的剪枝,不过只需要考虑行就行了,从空格最少的行开始搜索。

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<map>
      4 #include<set>
      5 #include<iostream>
      6 #include<cstring>
      7 #include<algorithm>
      8 #include<vector>
      9 #include<cmath> 
     10 #include<queue>
     11 
     12 #define inf 0x7f7f7f7f
     13 using namespace std;
     14 typedef long long LL;
     15 typedef pair<int, int> pr;
     16 
     17 int mat[10][10];
     18 bool visrow[10][10];
     19 bool viscol[10][10];
     20 bool vissqu[10][10];
     21 
     22 int ans = -1;
     23 vector<pr>zeros;
     24 int n = 0;
     25 
     26 int getscore()
     27 {
     28     int tmp = 0;
     29     for(int i = 0; i < 9; i++){
     30         for(int j = 0; j < 9; j++){
     31             tmp += mat[i][j] * 6;
     32         }
     33     }
     34     for(int k = 1; k < 5; k++){
     35         for(int i = 0 + k; i < 9 - k; i++){
     36             for(int j = 0 + k; j < 9 - k; j++){
     37                 tmp += mat[i][j];
     38             }
     39         }
     40     }
     41     
     42     return tmp;
     43 }
     44 
     45 void dfs(int id)
     46 {
     47     if(id == n){
     48 //        for(int i = 0; i < 9; i++){
     49 //            for(int j = 0; j < 9; j++){
     50 //                printf("%d ", mat[i][j]);
     51 //            }
     52 //            printf("
    ");
     53 //        }
     54 //        printf("%d
    
    ", getscore());
     55         
     56         ans = max(ans, getscore());
     57     }
     58     int i = zeros[id].first;
     59     int j = zeros[id].second;
     60     for(int k = 1; k <= 9; k++){
     61         if(!visrow[i][k] && !viscol[j][k] && !vissqu[i / 3 * 3+ j / 3][k]){
     62             mat[i][j] = k;
     63             visrow[i][k] = viscol[j][k] = vissqu[i / 3 * 3+ j / 3][k] = true;
     64             dfs(id + 1);
     65             visrow[i][k] = viscol[j][k] = vissqu[i / 3 * 3+ j / 3][k] = false;
     66             mat[i][j] = 0;
     67         }
     68     }
     69     return;
     70 }
     71 
     72 vector<int>zero[10];
     73 struct node{
     74     int row, cnt;
     75 }rows[10];
     76 
     77 bool cmp(node a, node b)
     78 {
     79     return a.cnt < b.cnt;
     80 }
     81 
     82 int main()
     83 {
     84     for(int i = 0; i < 9; i++){
     85         rows[i].row = i;
     86         for(int j = 0; j < 9; j++){
     87             scanf("%d", &mat[i][j]);
     88             if(mat[i][j]){
     89                 visrow[i][mat[i][j]] = true;
     90                 viscol[j][mat[i][j]] = true;
     91                 vissqu[i / 3 * 3+ j / 3][mat[i][j]] = true;
     92             }
     93             else{
     94                 rows[i].cnt++;
     95                 zero[i].push_back(j);
     96                 n++;
     97             }
     98         }
     99     }
    100     sort(rows, rows + 9, cmp);
    101     for(int i = 0; i < 9; i++){
    102         int r = rows[i].row;
    103         for(int j = 0; j < rows[i].cnt; j++){
    104             zeros.push_back(make_pair(r, zero[r][j]));
    105         }
    106     }
    107     
    108     dfs(0);
    109     printf("%d
    ", ans);
    110     
    111     return 0;
    112 }
  • 相关阅读:
    Google TensorFlow 机器学习框架介绍和使用
    Linux下chkconfig命令详解转载
    wireshark----linux
    linux 开机自启转载
    linux 开机自启
    linux 开机自启脚本
    当进行make命令学习是出现error trying to exec 'cc1': execvp: No such file or directory
    centos6.4安装GCC
    安装cmake
    整型数转字符串
  • 原文地址:https://www.cnblogs.com/wyboooo/p/10357496.html
Copyright © 2020-2023  润新知