洛谷P1074 靶形数独

论坛 期权论坛 脚本     
匿名网站用户   2020-12-19 21:55   28   0

Description:

写一个做数独的程序,但是这个数独有一点不同的是,每个格子有一个权值,权值与在格子上的数字乘积之和为总分,求最大能有多少分。

格子的权值规律如下

从白色的框到中央,依次为6,7,8,9,10

Input:

数独局面

Output:

answer

Analysis:

框架上就是dfs搜索,但是要有一个贪心的策略是,从有最少空格的行开始,因为,越少的空格在某一行就越能确定答案,可以减少dfs树的深度。里面还有一些细节,比如Get_point函数的写法上就有递推的意思。

#define _CRT_SECURE_NO_WARNINGS  
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<sstream>
#include<cmath>
#include<iterator>
#include<bitset>
#include<stdio.h>
#include<unordered_set>
#include<unordered_map>
#include<ctime>
#include<assert.h>
#include<cstring>
#include<array>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
typedef  long long LL;
const int INF = 1 << 30;
const int maxn = 11;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1);

int pic[maxn][maxn],n,tot_id;
int vis[3][10][10],ans;
vector<pair<int, int> > rows;
vector < pair<int, int> >id2cor;
inline int Get_grid(int r, int c) {
 return ((r - 1) / 3 * 3 + (c - 1) / 3);
}
inline int Get_point(int r, int c) {
 if (r == 1 || r == 9 || c == 1 || c == 9) return 6;
 if (r == 2 || r == 8 || c == 2 || c == 8) return 7;
 if (r == 3 || r == 7 || c == 3 || c == 7) return 8;
 if (r == 4 || r == 6 || c == 4 || c == 6) return 9;
 if (r == 5 || c == 5) return 10;
}
inline bool OK(int r, int c, int g,int num) {
 return !vis[0][r][num] && !vis[1][c][num] && !vis[2][g][num];
}

void Precal() {
 rows.clear();
 n = 9;
 _rep(i, 1, n) {
  int cnt = 0;
  _rep(j, 1, n)if (pic[i][j] == 0) cnt++;
  rows.push_back({ cnt,i });
 }
 sort(rows.begin(), rows.end());
 ans = -1;

 memset(vis, 0, sizeof(vis));
 _rep(i,1,n)
  _rep(j, 1, n) if(pic[i][j]){
  int num = pic[i][j];
  int g = Get_grid(i, j);
  vis[0][i][num] = vis[1][j][num] = vis[2][Get_grid(i, j)][num] = 1;
 }

 tot_id = 0;
 id2cor.resize(81);
 for(auto it:rows) {
  int row = it.second;
  _rep(j, 1, n)if (!pic[row][j]) {
   id2cor[tot_id++] = { row,j };
  }
 }
}

int Cal() {
 int res = 0;
 _rep(i,1,n)
  _rep(j, 1, n) {
  res += Get_point(i, j)*pic[i][j];
 }
 return res;
}

void DFS(int depth) {
 if (depth == tot_id) {
  int tmp = Cal();
  ans = max(tmp, ans);
  return;
 }

 int row = id2cor[depth].first, col = id2cor[depth].second;
 int g = Get_grid(row, col);
 _rep(num, 1, n) {
  if (OK(row, col, g,num)){
   vis[0][row][num] = vis[1][col][num] = vis[2][g][num] = 1;
   pic[row][col] = num;
   DFS(depth + 1);
   pic[row][col] = 0;
   vis[0][row][num] = vis[1][col][num] = vis[2][g][num] = 0;
  }
 }

}

int main()
{


 ios_base::sync_with_stdio(0);//用这个
 cin.tie(0);                    //就能防止cin超时orz

 _rep(i, 1, 9)
  _rep(j,1,9){
  cin >> pic[i][j];
 }
 Precal();
 DFS(0);
 cout << ans << endl;
 

 return 0;
}

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP