列表

详情


NC21603. 出题人的矩阵

描述

给你一个3*3的矩阵(数字1-9各出现一次),每次可以交换相邻的两个数,问最少操作几次可以变成3阶幻方
幻方是一种将数字安排在正方形格子中,使每行、列和对角线上的数字和都相等的方法。

输入描述

第一行包含1个整数T,表示有T组数据。
接下来的3T 行,每行3 个正整数,每3 行组合起来表示一个询问。保证数据合法.

输出描述

共T 行,每行一个正整数表示对应输入数据的最少操作次数

示例1

输入:

3 
7 8 9 
1 2 3 
4 5 6
6 1 8 
7 5 3 
2 9 4 
1 2 8 
3 5 4 
6 7 9

输出:

8
0
5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 319ms, 内存消耗: 8036K, 提交时间: 2019-09-30 17:19:25

#include <bits/stdc++.h>
using namespace std;
int fac[]={1,1,2,6,24,120,720,5040,40320,362880};
int ans[370000];
string mp[]={"672159834","834159672","294753618","492357816","816357492","618753294","438951276","276951438"};
int gethash(string s){
    int ans=0;
    for(int i=0;i<8;i++){
        int cnt=0;
        for(int j=i+1;j<9;j++){
            if(s[j]<s[i])cnt++;
        }
        ans+=fac[8-i]*cnt;
    }
    return ans;
}
struct node{string s;int step;node(string s,int step):s(s),step(step){}};
queue<node>q;
int dir[12][2]={{0,1},{1,2},{3,4},{4,5},{6,7},{7,8},
                {0,3},{3,6},{1,4},{4,7},{2,5},{5,8}};

void bfs(){
    for(int i=0;i<8;i++){ans[gethash(mp[i])]=0;q.push(node(mp[i],0));}
    while(!q.empty()){
        node now=q.front();q.pop();
        //if(ans[gethash(now.s)]<now.step)continue;
        for(int i=0;i<12;i++){
            swap(now.s[dir[i][0]],now.s[dir[i][1]]);
            int id=gethash(now.s);
            if(ans[id]>now.step+1){ans[id]=now.step+1;q.push(node(now.s,now.step+1));}
            swap(now.s[dir[i][0]],now.s[dir[i][1]]);
        }
    }
}
string s;
int main(){
    int T,a;
    scanf("%d",&T);
    for(int i=0;i<fac[9];i++)ans[i]=0x3f3f3f3f;
    //for(int i=0;i<8;i++)
    bfs();
    //for(int i=0;i<8;i++)cout<<ans[gethash(mp[i])]<<endl;
    while(T--){
        s.clear();
        for(int i=0;i<9;i++)scanf("%d",&a),s+=char(a+'0');
        //cout<<s<<endl;
        printf("%d\n",ans[gethash(s)]);
    }
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 256ms, 内存消耗: 6756K, 提交时间: 2019-01-26 16:54:48

#include<bits/stdc++.h>
using namespace std;
const int fac[]={1,1,2,6,24,120,720,5040,40320,362880};
const string final[]={"672159834","834159672","294753618","492357816","816357492","618753294","438951276","276951438"};
int ans[370000];

int gethash(string st) {
	int res=0;
	for (int i=0;i<8;i++) {
		int cnt=0;
		for (int j=i+1;j<9;j++) if (st[i]>st[j]) cnt++;
		res+=cnt*fac[8-i];
	}
	return res;
}

queue<string> q;
const int dir[12][2]={{0,1},{1,2},{3,4},{4,5},{6,7},{7,8},{0,3},{3,6},{1,4},{4,7},{2,5},{5,8}};
void bfs() {
	memset(ans,0x3f,sizeof(ans));
	for (int i=0;i<8;i++) {
		ans[gethash(final[i])]=0;
		q.push(final[i]);
	}
	while (!q.empty()) {
		string now=q.front(); q.pop();
		int nowh=gethash(now);
		for (int i=0;i<12;i++) {
			swap(now[dir[i][0]],now[dir[i][1]]);
			int h=gethash(now);
			if (ans[h]>ans[nowh]+1) {
				ans[h]=ans[nowh]+1;
				q.push(now);
			}
			swap(now[dir[i][0]],now[dir[i][1]]);
		}
	}
}

int main()
{
	int T; scanf("%d",&T);
	bfs();
	string s;
	while (T--) {
		s.clear();
		for (int i=1;i<=9;i++) {
			int x; scanf("%d",&x);
			s+=(char)(x+'0');
		}
		printf("%d\n",ans[gethash(s)]);
	}
	return 0;
}

上一题