1. 程式人生 > >【構造】地轉偏向力

【構造】地轉偏向力

題意:

在這裡插入圖片描述


分析:

首先,
一定要寫個暴力!
一定要寫個暴力!
一定要寫個暴力!

手玩真心不好搞!
手玩真心不好搞!
手玩真心不好搞!

通過寫一個5*5以內的暴力,我們可以找到一些特殊的方案:
存在這樣一種方案,滿足:
在這裡插入圖片描述
如圖所示的一個五宮格中,存在一種方案,滿足從1->2-3->4-1的一條迴路(其中2與3,1與4是直接相連),並經過了五宮格內所有其餘的點。
方案如下:
在這裡插入圖片描述

還存在一種5*5以內的方案,滿足:
在這裡插入圖片描述
1->2-3->4-1的一條迴路(其中2與3,1與4是直接相連),並經過了所有其餘五宮格內的點。
方案如下:
在這裡插入圖片描述
有了這兩種方案,我們就可以得到一個合法的遍歷所有格子的方法了。
在這裡插入圖片描述


把直接相連的那兩條邊斷掉,然後連上另一個圖。最終,整個圖就形成了:由數個小環拆邊,接入後而成的一個大環。

實際操作中,其實不需要管那些所謂的刪邊加邊之類的。詳見程式碼

#include<cstdio>
#include<cstring>
#include<algorithm>
#define SF scanf
#define PF printf
#define MAXN 1010
using namespace std;
int Direct[5][5]={
	{ 1,14, 6, 9,15},
	{21,11, 3,18,23},
	{ 5, 8,25
,13, 7}, { 2,17,22,10,16}, {20,12, 4,19,24} }; int Rotate[5][5]={ { 1,11,18, 4,10}, {16,22, 8,13,23}, {19, 5,25,20, 6}, { 2,12,17, 3, 9}, {15,21, 7,14,24} }; int used[MAXN][MAXN],ans[MAXN][MAXN],tmp[MAXN][MAXN]; int dir[6][4]={{0,1},{1,0},{0,-1},{-1,0}}; int m,cnt; void rotate(int x,int y){ for(int i=
0;i<5;i++) for(int j=0;j<5;j++) tmp[i][j]=ans[4-j+x][i+y]; for(int i=0;i<5;i++) for(int j=0;j<5;j++) ans[i+x][j+y]=tmp[i][j]; } void dfs(int x,int y,int d){ if(x<0||y<0||x>=m||y>=m||used[x][y]) return ; used[x][y]=1; int xx=x+dir[d][0],yy=y+dir[d][1]; if(xx>=0&&yy>=0&&xx<m&&yy<m&&used[xx][yy]==0){ for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(Direct[i][j]<=6) ans[i+x*5][j+y*5]=cnt+Direct[i][j]; cnt+=6; dfs(xx,yy,d); for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(Direct[i][j]>6) ans[i+x*5][j+y*5]=cnt+Direct[i][j]-6; cnt+=19; for(int i=0;i<d;i++) rotate(x*5,y*5); } else{ for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(Rotate[i][j]<=6) ans[i+x*5][j+y*5]=cnt+Rotate[i][j]; cnt+=6; xx=x+dir[(d+1)%4][0]; yy=y+dir[(d+1)%4][1]; dfs(xx,yy,(d+1)%4); for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(Rotate[i][j]>6) ans[i+x*5][j+y*5]=cnt+Rotate[i][j]-6; cnt+=19; for(int i=0;i<d;i++) rotate(x*5,y*5); } } int main(){ int n; SF("%d",&n); m=n/5; dfs(0,0,0); for(int i=0;i<n;i++){ for(int j=0;j<n;j++) PF("%d ",ans[i][j]); PF("\n"); } }

另外,附帶檢測和暴力程式碼:
暴力:

#include<cstdio>
#include<cstring>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 1010
using namespace std;
int used[MAXN][MAXN];
int w[10][5]={{3,0},{-3,0},{0,3},{0,-3},{2,2},{2,-2},{-2,2},{-2,-2}};
int ans[MAXN][MAXN],flag;
int n,m,edx,edy;
void dfs(int x,int y,int cnt=1){
	used[x][y]=cnt;
	if(cnt+m==n*n&&(used[5][3]-used[3][5])==-1&&abs(used[1][1]-used[3][3])==1&&((x==1&&y==4)||(x==4&&y==1))){
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				ans[i][j]=used[i][j];
		flag=1;	
	}
	for(int j=0;j<8;j++){
		int xx=x+w[j][0];
		int yy=y+w[j][1];
		if(xx>=1&&yy>=1&&xx<=n&&yy<=n&&used[xx][yy]==0)
			dfs(xx,yy,cnt+1);	
		if(flag)
			return ;
	}
	used[x][y]=0;
}
int main(){
	int stx,sty;
	n=5;
	SF("%d%d",&stx,&sty);
	dfs(stx,sty);
	if(flag){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++)
				PF(",%2d",(26-ans[i][j])%25+1);
			PF("\n");	
		}
	}
	else
		PF("No answer!\n");
}

檢測:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define SF scanf
#define PF printf
#define MAXN 1010
using namespace std;
int n;
int a[MAXN][MAXN];
int w[10][5]={{3,0},{-3,0},{0,3},{0,-3},{2,2},{2,-2},{-2,2},{-2,-2}};
int main(){
	SF("%d",&n);
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			SF("%d",&a[i][j]);
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++){
			bool flag=0;
			for(int d=0;d<8;d++){
				int x=i+w[d][0];
				int y=j+w[d][1];
				if(x>=0&&y>=0&&x<n&&y<n&&a[x][y]==(a[i][j])%(n*n)+1)
					flag=1;
			}
			if(flag==0){
				PF("[%d %d]",i,j);
				PF("Error!");
				return 0;
			}
		}
	PF("Correct Answer!");
}