• 洛谷1549 棋盘问题(2)


    原题链接

    爆搜题。
    先用线性筛预处理出素数,并直接暴力循环预处理出那些数和哪些数之间能拼成素数,当然可以再疯狂点,直接预处理出每两个数可以和哪些数拼成素数(反正(n)小,随你预处理)。
    然后爆搜的时候注意搜索顺序,先搜第一行第一列,以保证第一行第一列之和最小。
    然而普通的搜索顺序搜除去第一行第一列剩下的部分会有一个问题,即从小到大搜会导致(n = 9)很慢,若从大到小搜会导致(n = 7)很慢。
    我的程序从大到小搜的话,(n = 7)需要(1s)多点,其它秒出,不过经测试开了(O2)在本地或是洛谷(IDE)上都能在(0.9s)内过。
    不过我还不够满意,既然不能一直从小到大,也不能一直从大到小,那就折中一下呗,上随机数。
    测试了(5)个随机数种子,总算让我找到一个能够使得程序秒出(1sim 10)所有数据的了(甚至可以出(11,12))。
    这样总算是真正的(A)了此题了。
    另外,我发现这个随机数种子仅是使得我本地能过,在洛谷(IDE)上却无法出(9)的数据,可能是因为操作系统不同导致相同随机数种子的结果不同,所以若真要搞过,还是(time(NULL))看人品吧。。

    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    const int N = 13;
    const int M = N * N;
    const int K = M << 1;
    int a[N][N], p[M][M], pr[K], L[M], P[M][M][M], PL[M][M], n, l, o;
    bool v[K], vis[M], pi[M][M];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void ri(int &x, int &y)
    {
    	y++;
    	if (y > n)
    	{
    		y = 1;
    		x++;
    	}
    }
    inline void dw(int &x, int &y)
    {
    	x++;
    	if (x > n)
    		x = y = 2;
    }
    bool dfs(int x, int y)
    {
    	if (x > n)
    		return true;
    	int i, le = a[x][y - 1], u = a[x - 1][y], xx = x, yy = y, g;
    	if (!(x ^ 1) && y ^ 1)//搜第一行
    	{
    		ri(xx, yy);
    		for (i = 1; i <= L[le]; i++)
    			if (!vis[g = p[le][i]])
    			{
    				a[x][y] = g;
    				vis[g] = 1;
    				if (dfs(xx, yy))
    					return true;
    				vis[g] = 0;
    				a[x][y] = 0;
    			}
    	}
    	else
    		if (x ^ 1 && !(y ^ 1))//搜第一列
    		{
    			dw(xx, yy);
    			for (i = 1; i <= L[u]; i++)
    				if (!vis[g = p[u][i]])
    				{
    					a[x][y] = g;
    					vis[g] = 1;
    					if (dfs(xx, yy))
    						return true;
    					vis[g] = 0;
    					a[x][y] = 0;
    				}
    		}
    		else
    		{
    			ri(xx, yy);
    			if (!(yy ^ 1))
    				yy++;
    			if (rand() & 1)//随机数折中
    				for (i = PL[le][u]; i; i--)//从大到小搜
    				{
    					g = P[le][u][i];
    					if (!vis[g])
    					{
    						a[x][y] = g;
    						vis[g] = 1;
    						if (dfs(xx, yy))
    							return true;
    						vis[g] = 0;
    						a[x][y] = 0;
    					}
    				}
    			else
    				for (i = 1; i <= PL[le][u]; i++)//从小到大搜
    				{
    					g = P[le][u][i];
    					if (!vis[g])
    					{
    						a[x][y] = g;
    						vis[g] = 1;
    						if (dfs(xx, yy))
    							return true;
    						vis[g] = 0;
    						a[x][y] = 0;
    					}
    				}
    		}
    	return false;
    }
    int main()
    {
    	srand(9982123);//仅本地能过,洛谷IDE无法过9的数据,不行还是上time(NULL)吧
    	int m, i, j, k, x;
    	n = re();
    	if (!(n ^ 1))//特判掉1
    	{
    		printf("NO");
    		return 0;
    	}
    	o = n * n;
    	m = o << 1;
    	v[0] = v[1] = 1;
    	for (i = 2; i <= m; i++)//线性筛素数
    	{
    		if (!v[i])
    			pr[++l] = i;
    		for (j = 1; j <= l; j++)
    		{
    			if (i * pr[j] > m)
    				break;
    			v[i * pr[j]] = 1;
    			if (!(i % pr[j]))
    				break;
    		}
    	}
    	for (i = 1; i < o; i++)
    		for (j = i + 1; j <= o; j++)//预处理每个数能和哪些数的和是素数
    			if (!v[i + j])
    			{
    				p[i][++L[i]] = j;
    				p[j][++L[j]] = i;
    				pi[i][j] = pi[j][i] = 1;
    			}
    	for (i = 1; i <= o; i++)
    		sort(p[i] + 1, p[i] + L[i] + 1);//排序
    	for (i = 1; i < o; i++)//预处理每两个数能和哪些数拼成素数
    		for (j = i + 1, m = L[i]; j <= o; j++)
    			for (k = 1; k <= m; k++)
    				if (pi[x = p[i][k]][j])
    					P[i][j][++PL[i][j]] = P[j][i][++PL[j][i]] = x;
    	a[1][1] = 1;
    	vis[1] = 1;
    	if (dfs(1, 2))
    		for (i = 1; i <= n; i++, printf("
    "))
    			for (j = 1; j <= n; j++)
    				printf("%d ", a[i][j]);
    	else
    		printf("NO");
    	return 0;
    }
    
  • 相关阅读:
    全代码实现ios-4
    集训第一次周赛题目及题解
    网站登录时密码忘记,通过向邮箱发送验证链接实现重置密码的实现方法
    hdu 1861-游船出租
    c#获取或修改配置文件
    今天做php经典实例,发现,我是对的,面试官给我说错了
    HDU 4637 Rain on your Fat brother 线段与半圆和线段交 简单题
    Qt之图标切分与合并
    标准容器的共性及举例
    如何提高数据库update更新的速度
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9854458.html
Copyright © 2020-2023  润新知