洛谷 P1213 时钟 &&IOI 1994 The Clocks

IOI 1994 The Clocks

题目描述

考虑将如此安排在一个 3 x 3 行列中的九个时钟:

目标要找一个最小的移动顺序将所有的指针指向12点。下面原表格列出了9种不同的旋转指针的方法,每一种方法都叫一次移动。选择1到9号移动方法,将会使在表格中对应的时钟的指针顺时针旋转90度。

移动方法 受影响的时钟

1 ABDE

2 ABC

3 BCEF

4 ADG

5 BDEFH

6 CFI

7 DEGH

8 GHI

9 EFHI

Example

[但这可能不是正确的方法,请看下面]

输入输出格式

输入格式:

第1-3行: 三个空格分开的数字,每个数字表示一个时钟的初始时间,3,6,9,12。数字的含意和上面第一个例子一样。


输出格式:

单独的一行包括一个用空格分开的将所有指针指向12:00的最短移动顺序的列表。

如果有多种方案,输出那种使其连接起来数字最小的方案。(举例来说5 2 4 6 < 9 3 1 1)。

输入输出样例

输入样例#1:

9 9 12
6 6 6
6 3 6

输出样例#1:

4 5 8 9

说明

题目翻译来自NOCOW。

USACO Training Section 1.4

暴力bfs 在vijos 上是可以A的

但是在洛谷 会被卡掉两个点  1.3s 死活没法再优化了

若有会的dalao 帮帮我

换dfs

每一种变换 最多变3次 第四次就回到原来的状态

所以我们可以dfs每一种变换方式的次数 最多三次

bfs超时数据 dfs 0.1s毫无压力

#include <queue>
#include <ctime>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>

/*int z[9][9]={{1,1,0,1,1,0,0,0,0},
			 {1,1,1,0,0,0,0,0,0},
			 {0,1,1,0,1,1,0,0,0},
			 {1,0,0,1,0,0,1,0,0},
			 {0,1,0,1,1,1,0,1,0},
			 {0,0,1,0,0,1,0,0,1},
			 {0,0,0,1,1,0,1,1,0},
			 {0,0,0,0,0,0,1,1,1},
			 {0,0,0,0,1,1,0,1,1},
			};*/

int z[10][10] = {{0},{1,2,4,5},{1,2,3},{2,3,5,6},{1,4,7},{2,4,5,6,8},
                  {3,6,9},{4,5,7,8},{7,8,9},{5,6,8,9}};

int s[10];

struct node {
	int s[10];
	int cnt;
	int path[100];
	friend bool operator < (node x,node y) {
		return x.cnt>y.cnt;
	}
};
node a,now,t;

bool f[4][4][4][4][4][4][4][4][4];

inline void read(int&x) {
	register char c=getchar();
	for(x=0;!isdigit(c);c=getchar());
	for(;isdigit(c);x=x*10+c-48,c=getchar());
}

inline bool pd(int*p) {
	for(int i=0;i<9;++i) if(p[i]) return false;
	return true;
}

inline bool check(int*p) {
	if(f[p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]][p[7]][p[8]]) return false;
	f[p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]][p[7]][p[8]]=1;
	return true;
}

inline void BFS() {
	std::priority_queue<node> q;
	memcpy(a.s,s,sizeof s);
	q.push(a);
	while(!q.empty()) {
		now=q.top();
		q.pop();
		for(int i=1;i<=9;++i) {
			t=now;
			if(pd(now.s)) {
				std::sort(now.path+1,now.path+now.cnt+1);
				for(int k=1;k<=now.cnt;++k) printf("%d ",now.path[k]);
				return;
			}
			for(int j=0;z[i][j];++j) {
				++t.s[z[i][j]-1];
				if(t.s[z[i][j]-1]>=4) t.s[z[i][j]-1]-=4;
			}
			if(check(t.s)) {
				t.path[++t.cnt]=i;
				q.push(t);
			}
		}
	}
	return;
}

int hh() {
	freopen("1.out","r",stdin);
	int t=clock();
	for(int x,i=0;i<9;++i)
	   read(x),x=(x/3)%4,s[i]=x;//
	f[s[0]][s[1]][s[2]][s[3]][s[4]][s[5]][s[6]][s[7]][s[8]]=1;
	BFS();
	printf("%d\n",clock());
	return 0;
}

int sb=hh();
int main(int argc,char**argv) {;}

  

#include <queue>
#include <ctime>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>

const int MAXN=10;

int z[9][9]={{1,1,0,1,1,0,0,0,0},
			 {1,1,1,0,0,0,0,0,0},
			 {0,1,1,0,1,1,0,0,0},
			 {1,0,0,1,0,0,1,0,0},
			 {0,1,0,1,1,1,0,1,0},
			 {0,0,1,0,0,1,0,0,1},
			 {0,0,0,1,1,0,1,1,0},
			 {0,0,0,0,0,0,1,1,1},
			 {0,0,0,0,1,1,0,1,1},
			};

int s[MAXN],tmp[MAXN],ans[MAXN];

inline void read(int&x) {
	register char c=getchar();
	for(x=0;!isdigit(c);c=getchar());
	for(;isdigit(c);x=x*10+c-48,c=getchar());
}

inline bool check() {
	for(int i=0;i<9;++i) if(tmp[i]) return false;
	return true;
}

inline void print() {
	for(int i=0;i<9;++i)
	  for(int j=0;j<ans[i];++j)
	    printf("%d ",i+1);
	exit(0);
}

inline void DFS(int step) {
	memcpy(&tmp,&s,sizeof tmp);
	for(int i=0;i<9;++i)
	  for(int j=0;j<9;++j)
	    tmp[i]=(tmp[i]+z[j][i]*ans[j])%4;
	if(check()) {print();}
	if(step==9) return;
	for(int i=0;i<4;++i)
	  ans[step]=i,DFS(step+1);
	return;
}

int hh() {
//	freopen("1.out","r",stdin);
//	int t=clock();
	for(int x,i=0;i<9;++i)
	   read(x),x=(x/3)%4,s[i]=x;
	DFS(0);
//	printf("%d\n",clock());
	return 0;
}

int sb=hh();
int main(int argc,char**argv) {;}

  

时间: 2024-10-28 19:58:16

洛谷 P1213 时钟 &&IOI 1994 The Clocks的相关文章

Vijos——T 1016 北京2008的挂钟 || 洛谷—— P1213 时钟

https://www.luogu.org/problem/show?pid=1213 题目描述 考虑将如此安排在一个 3 x 3 行列中的九个时钟: 目标要找一个最小的移动顺序将所有的指针指向12点.下面原表格列出了9种不同的旋转指针的方法,每一种方法都叫一次移动.选择1到9号移动方法,将会使在表格中对应的时钟的指针顺时针旋转90度. 移动方法 受影响的时钟 1 ABDE 2 ABC 3 BCEF 4 ADG 5 BDEFH 6 CFI 7 DEGH 8 GHI 9 EFHI Example

洛谷 P1854 花店橱窗布置

题目描述 某花店现有F束花,每一束花的品种都不一样,同时至少有同样数量的花瓶,被按顺序摆成一行,花瓶的位置是固定的,从左到右按1到V顺序编号,V是花瓶的数目.花束可以移动,并且每束花用1到F的整数标识.如果I < J,则花束I必须放在花束J左边的花瓶中.例如,假设杜鹃花的标识数为1,秋海棠的标识数为2,康乃馨的标识数为3,所有花束在放入花瓶时必须保持其标识数的顺序,即杜鹃花必须放在秋海棠左边的花瓶中,秋海棠必须放在康乃馨左边的花瓶中.如果花瓶的数目大于花束的数目,则多余的花瓶必须空,即每个花瓶只

洛谷 P2709 BZOJ 3781 小B的询问

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3

洛谷1231 教辅的组成

洛谷1231 教辅的组成 https://www.luogu.org/problem/show?pid=1231 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习题.然而出现在他眼前的书多得数不胜数,其中有书,有答案,有练习册.已知一个完整的书册均应该包含且仅包含一本书.一本练习册和一份答案,然而现在全都乱做了一团.许多书上面的字迹都已经模糊了,然而HansBug还是可

洛谷教主花园dp

洛谷-教主的花园-动态规划 题目描述 教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值. 教主最喜欢3种树,这3种树的高度分别为10,20,30.教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高. 输入输出格式 输入格式: 输入文件garden.in的第1行为一个正整数n,表示需要种的

洛谷 P2801 教主的魔法 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=2801 题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的身高一开始都是不超过1000的正整数.教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W.(虽然L=R时并不

洛谷P1466 集合 Subset Sums

洛谷P1466 集合 Subset Sums这题可以看成是背包问题 用空间为 1--n 的物品恰好填充总空间一半的空间 有几种方案 01 背包问题 1.注意因为两个交换一下算同一种方案,所以最终 要 f [ v ] / 2 2.要开 long long 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string&g

洛谷P1160 队列安排 链表

洛谷P1160 队列安排   链表 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <string> 6 #include <algorithm> 7 #include <iomanip> 8 #include <iostream> 9 using namespace std

洛谷 P3367 并查集模板

#include<cstdio> using namespace std; int n,m,p; int father[2000001]; int find(int x) { if(father[x]!=x) father[x]=find(father[x]); return father[x]; } void unionn(int i,int j) { father[j]=i; } int main() { scanf("%d%d",&n,&m); for