zoukankan      html  css  js  c++  java
  • [luoguP1074] 靶形数独(搜索)

    传送门

    75分,太菜,不会优化了,吐了。

    几点优化。

    1.先搜索容易确定的位置

    2.从中心往周围搜

    3.枚举数字的时候倒序枚举

    4.如果没有枚举到的数字都是最优情况的话也不能比当前ans大就剪枝

    5.位运算

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #define max(x, y) ((x) > (y) ? (x) : (y))
    #define tu(i, j) (((i) - 1) / 3 * 3 + ((j) - 1) / 3 + 1)
    
    int ans = -1, cnt;
    int hang[10], lie[10], jiu[10], shu[10], a[10][10], num[10][10], point[11];
    
    struct node
    {
    	int pt, x, y, z;
    	node(int pt = 0, int x = 0, int y = 0, int z = 0) : pt(pt), x(x), y(y), z(z) {}
    }p[101];
    
    inline int read()
    {
    	int x = 0, f = 1;
    	char ch = getchar();
    	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
    	return x * f;
    }
    
    inline bool cmp(node x, node y)
    {
    	return x.z > y.z || (x.z == y.z && x.pt > y.pt);
    }
    
    inline int pd(int x, int y)
    {
    	if(x == 1 || x == 9 || y == 1 || y == 9) return 6;
    	if(x == 2 || x == 8 || y == 2 || y == 8) return 7;
    	if(x == 3 || x == 7 || y == 3 || y == 7) return 8;
    	if(x == 4 || x == 6 || y == 4 || y == 6) return 9;
    	return 10;
    }
    
    inline bool check(int sum)
    {
    	int i, j, k, top;
    	k = 10;
    	top = point[k];
    	for(i = 9; i >= 1; i--)
    		for(j = 1; j <= 9 - shu[i]; j++)
    			if(top) top--, sum += i * k;
    			else
    			{
    				while(!top && k > 6) k--, top = point[k];
    				top--;
    				sum += i * k;
    			}
    	return sum > ans;
    }
    
    inline void dfs(int x, int y, int k, int sum)
    {
    	if(k > cnt)
    	{
    		ans = max(ans, sum);
    		return;
    	}
    	for(int i = 9; i >= 1; i--)
    		if(!(hang[x] & (1 << i - 1)) && !(lie[y] & (1 << i - 1)) && !(jiu[tu(x, y)] & (1 << i - 1)))
    		{
    			shu[i]++;
    			point[pd(x, y)]--; 
    			lie[y] |= 1 << i - 1;
    			hang[x] |= 1 << i - 1;
    			jiu[tu(x, y)] |= 1 << i - 1;
    			if(check(sum + p[k].pt * i)) dfs(p[k + 1].x, p[k + 1].y, k + 1, sum + p[k].pt * i);
    			jiu[tu(x, y)] ^= 1 << i - 1;
    			hang[x] ^= 1 << i - 1;
    			lie[y] ^= 1 << i - 1;
    			point[pd(x, y)]++;
    			shu[i]--;
    		}
    }
    
    int main()
    {
    	int i, j, k, l, x, sum = 0;
    	point[6] = 32;
    	point[7] = 24;
    	point[8] = 16;
    	point[9] = 8;
    	point[10] = 1;
    	for(i = 1; i <= 9; i++)
    		for(j = 1; j <= 9; j++)
    		{
    			shu[a[i][j] = read()]++;
    			sum += a[i][j] * pd(i, j);
    			if(a[i][j])
    			{
    				point[pd(i, j)]--;
    				lie[j] |= 1 << a[i][j] - 1;
    				hang[i] |= 1 << a[i][j] - 1;
    				jiu[tu(i, j)] |= 1 << a[i][j] - 1;
    			}
    		}
    	for(i = 1; i <= 9; i++)
    		for(j = 1; j <= 9; j++)
    		{
    			for(k = 1; k <= 9; k++)
    				if(a[i][k] && k != j)
    					num[i][j]++;
    			for(k = 1; k <= 9; k++)
    				if(a[k][j] && k != i)
    					num[i][j]++;
    			for(k = 1; k <= 9; k++)
    				for(l = 1; l <= 9; l++)
    					if(tu(i, j) == tu(k, l) && a[k][l] && !(i == k && j == l))
    						num[i][j]++;
    		}
    	for(i = 1; i <= 9; i++)
    		for(j = 1; j <= 9; j++)
    			if(!a[i][j])
    				p[++cnt] = node(pd(i, j), i, j, num[i][j]);
    	std::sort(p + 1, p + cnt + 1, cmp);
    	dfs(p[1].x, p[1].y, 1, sum);
    	printf("%d
    ", ans);
    	return 0;		
    }
    

      

  • 相关阅读:
    C#Type类中的IsAssignableFrom、IsInstanceOfType、IsSubclassOf
    C# IsAssignableFrom & IsInstanceOfType & IsSubclassOf & Is
    VS2017桌面应用程序打包成.msi或者.exe
    C# 10个常用特性
    ADO.NET 的六大对象及其关系图
    Expression表达式树(C#)
    表达式树 Expression Trees
    特性 Attribute
    C# 特性(attribute)
    Vue中使用axios
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/7274795.html
Copyright © 2011-2022 走看看