[WIT新生赛B题]跳棋

Pro

牛客

Sol

知道一个事:预处理所有的点再面对每一个询问花的时间可能更短

一个四维数组:ini[x][y][z][k]表示当1位置放x克,9位置放y克时总共有z种方法,每种方法第k个数是ini[x][y][z][k]

剪枝:易得每一条线值的和必为26(平均数乘棋子数)
所以就可以对已经搜出来的点剪一下枝

剩下的就是常规dfs

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<sstream>
using namespace std;
typedef long long LL;
#define PI acos(-1)
#define fin freopen("data.txt","r",stdin)
#define INF 2147483647
#define eps 1e-7
#define L 15
#define Ms(a,b) memset((a),(b),sizeof(a))
#define Fo(i,a,b) for(LL i=(a),_=(b); i<=_; i++)
#define Ro(i,b,a) for(LL i=(b),_=(a); i>=_; i--)
inline LL read() {
    
    
	LL x=0,f=1;char c=getchar();
    while(!isdigit(c)) {
    
    if(c=='-')f=-f;c=getchar();}
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48ll),c=getchar();
    return x*f;
}

int num[15] , ini[L][L][L][L] , n1 , n2 , vis[L] , top , t[L][L] , x1 , x2;

void dfs(int x) {
    
    
	if((x==6&&num[2]+num[3]+num[4]+num[5]!=26)||(x==9&&num[1]+num[3]+num[6]+num[8]!=26)||(x==12&&num[1]+num[4]+num[7]+num[11]!=26)||(x==12&&num[8]+num[9]+num[10]+num[11]!=26))
		return ;
	if(x==13) {
    
    
		if((num[2]+num[6]+num[9]+num[12]!=26)||(num[5]+num[7]+num[10]+num[12]!=26))
			return ;
		top++;
		Fo(i,1,12)
			ini[n1][n2][top][i]=num[i];			
		return ;
	}
	if(x==1||x==9) {
    
    
		dfs(x+1);
		return ;
	}
	Fo(i,1,12)
		if(!vis[i]) {
    
    
			vis[i]=1;
			num[x]=i;
			dfs(x+1);
			vis[i]=0;
		}
}

void sol() {
    
    
	Fo(i,1,12)
		Fo(j,1,12)
			if(i!=j) {
    
    
				Ms(vis,0);
				vis[i]=vis[j]=1;
				num[1]=i; num[9]=j;
				top=0; 
				n1=i; n2=j;
				dfs(1);
				t[i][j]=top;
			}
}

int main() {
    
    
//	fin;
	sol();
	while(scanf("%d%d",&x1,&x2)!=EOF) {
    
    
		if(!t[x1][x2])
			printf("-1\n");
		else {
    
    
			Fo(i,1,t[x1][x2]) {
    
    
				Fo(j,1,12)
					printf("%d ",ini[x1][x2][i][j]);
				printf("\n");
			}
		}
		printf("\n");
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/cls1277/article/details/110137930
今日推荐