关于标题
I(Interesting)T(Test)O(Of)N(Noip)
番外(论矩阵的妙用)
一道USACO的题:
The Clocks【搜索专题】
题目背景
USACO 1.4.2 (IOI’94)
搜索专题训练(一)
题目描述
考虑将如此安排在一个 3×3 行列中的九个时钟:
目标要找一个最小的移动顺序次将所有的指针指向12点.
下面原表格列出了 9 种不同的旋转指针的方法,每一种方法都叫一次移动。
选择 1 到 9 号移动方法,将会使在表格中对应的时钟的指针顺时针旋转90度。
移动方法 —– 受影响的时钟
— 1 ————— ABDE —–
— 2 ————— ABC ——
— 3 ————— BCEF ——
— 4 ————— ADG ——
— 5 ————– BDEFH —–
— 6 ————— CFI ——–
— 7 ————— DEGH —–
— 8 ————— GHI ——–
— 9 ————— EFHI ——–
比如一个例子:
但这可能不是正确的方法,请看下面。
输入格式
第 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
输出
4 5 8 9
这是我同学SZM的代码:
SZM.CPP
#include<bits/stdc++.h>
using namespace std;
int f[500005][4][4],num[4][4],done[500005],pre[500005];
int head,tail,ans=0;
bool p[4][4][4][4][4][4][4][4][4];
bool flag=false;
inline int add(int x)
{
x=x+1;
if(x==4) return 0;
else return x;
}
inline void work1(int x)
{
int a[4][4];
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
a[t][h]=f[x][t][h];
}
}
a[1][1]=add(a[1][1]);
a[1][2]=add(a[1][2]);
a[2][1]=add(a[2][1]);
a[2][2]=add(a[2][2]);
bool fuck=true;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
if(a[t][h]!=3)
{
fuck=false;
break;
}
}
if(fuck==false) break;
}
if(fuck==true)
{
int now=x,q[22],val=0;
flag=true;
q[++val]=1;
if(x!=1) q[++val]=done[x];
while(pre[now]!=0)
{
now=pre[now];
if(done[now]!=0)
{
q[++val]=done[now];
}
}
for(int t=val;t>=1;--t)
cout<<q[t]<<' ';
}
if(!p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]])
{
p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]]=true;
++tail;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
f[tail][t][h]=a[t][h];
if(a[t][h]>3) ans++;
}
}
pre[tail]=x,done[tail]=1;
}
}
inline void work2(int x)
{
int a[4][4];
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
a[t][h]=f[x][t][h];
}
}
a[1][1]=add(a[1][1]);
a[1][2]=add(a[1][2]);
a[1][3]=add(a[1][3]);
bool fuck=true;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
if(a[t][h]!=3)
{
fuck=false;
break;
}
}
if(fuck==false) break;
}
if(fuck==true)
{
int now=x,q[22],val=0;
flag=true;
q[++val]=2;
if(x!=1)q[++val]=done[x];
while(pre[now]!=0)
{
now=pre[now];
if(done[now]!=0)
{
q[++val]=done[now];
}
}
for(int t=val;t>=1;t--) cout<<q[t]<<' ';
}
if(!p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]])
{
p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]]=true;
tail++;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
f[tail][t][h]=a[t][h];
}
}
pre[tail]=x,done[tail]=2;
}
}
void work3(int x)
{
int a[4][4];
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
a[t][h]=f[x][t][h];
}
}
a[1][2]=add(a[1][2]);
a[1][3]=add(a[1][3]);
a[2][2]=add(a[2][2]);
a[2][3]=add(a[2][3]);
bool fuck=true;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
if(a[t][h]!=3)
{
fuck=false;
break;
}
}
if(fuck==false) break;
}
if(fuck==true)
{
int now=x,q[22],val=0;
flag=true;
q[++val]=3;
if(x!=1)q[++val]=done[x];
while(pre[now]!=0)
{
now=pre[now];
if(done[now]!=0)
{
q[++val]=done[now];
}
}
for(int t=val;t>=1;t--) cout<<q[t]<<' ';
}
if(!p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]])
{
p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]]=true;
tail++;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
f[tail][t][h]=a[t][h];
}
}
pre[tail]=x,done[tail]=3;
}
}
void work4(int x)
{
int a[4][4];
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
a[t][h]=f[x][t][h];
}
}
a[1][1]=add(a[1][1]);
a[2][1]=add(a[2][1]);
a[3][1]=add(a[3][1]);
bool fuck=true;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
if(a[t][h]!=3)
{
fuck=false;
break;
}
}
if(fuck==false) break;
}
if(fuck==true)
{
int now=x,q[22],val=0;
flag=true;
q[++val]=4;
if(x!=1)q[++val]=done[x];
while(pre[now]!=0)
{
now=pre[now];
if(done[now]!=0)
{
q[++val]=done[now];
}
}
for(int t=val;t>=1;t--) cout<<q[t]<<' ';
}
if(!p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]])
{
p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]]=true;
tail++;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
f[tail][t][h]=a[t][h];
}
}
pre[tail]=x,done[tail]=4;
}
}
void work5(int x)
{
int a[4][4];
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
a[t][h]=f[x][t][h];
}
}
a[1][2]=add(a[1][2]);
a[2][1]=add(a[2][1]);
a[2][2]=add(a[2][2]);
a[2][3]=add(a[2][3]);
a[3][2]=add(a[3][2]);
bool fuck=true;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
if(a[t][h]!=3)
{
fuck=false;
break;
}
}
if(fuck==false) break;
}
if(fuck==true)
{
int now=x,q[22],val=0;
flag=true;
q[++val]=5;
if(x!=1)q[++val]=done[x];
while(pre[now]!=0)
{
now=pre[now];
if(done[now]!=0)
{
q[++val]=done[now];
}
}
for(int t=val;t>=1;t--) cout<<q[t]<<' ';
}
if(!p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]])
{
p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]]=true;
tail++;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
f[tail][t][h]=a[t][h];
}
}
pre[tail]=x,done[tail]=5;
}
}
void work6(int x)
{
int a[4][4];
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
a[t][h]=f[x][t][h];
}
}
a[1][3]=add(a[1][3]);
a[2][3]=add(a[2][3]);
a[3][3]=add(a[3][3]);
bool fuck=true;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
if(a[t][h]!=3)
{
fuck=false;
break;
}
}
if(fuck==false) break;
}
if(fuck==true)
{
int now=x,q[22],val=0;
flag=true;
q[++val]=6;
if(x!=1)q[++val]=done[x];
while(pre[now]!=0)
{
now=pre[now];
if(done[now]!=0)
{
q[++val]=done[now];
}
}
for(int t=val;t>=1;t--) cout<<q[t]<<' ';
}
if(!p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]])
{
p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]]=true;
tail++;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
f[tail][t][h]=a[t][h];
}
}
pre[tail]=x,done[tail]=6;
}
}
void work7(int x)
{
int a[4][4];
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
a[t][h]=f[x][t][h];
}
}
a[2][1]=add(a[2][1]);
a[2][2]=add(a[2][2]);
a[3][1]=add(a[3][1]);
a[3][2]=add(a[3][2]);
bool fuck=true;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
if(a[t][h]!=3)
{
fuck=false;
break;
}
}
if(fuck==false) break;
}
if(fuck==true)
{
int now=x,q[22],val=0;
flag=true;
q[++val]=7;
if(x!=1)q[++val]=done[x];
while(pre[now]!=0)
{
now=pre[now];
if(done[now]!=0)
{
q[++val]=done[now];
}
}
for(int t=val;t>=1;t--) cout<<q[t]<<' ';
}
if(!p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]])
{
p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]]=true;
tail++;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
f[tail][t][h]=a[t][h];
}
}
pre[tail]=x,done[tail]=7;
}
}
void work8(int x)
{
int a[4][4];
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
a[t][h]=f[x][t][h];
}
}
a[3][1]=add(a[3][1]);
a[3][2]=add(a[3][2]);
a[3][3]=add(a[3][3]);
bool fuck=true;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
if(a[t][h]!=3)
{
fuck=false;
break;
}
}
if(fuck==false) break;
}
if(fuck==true)
{
int now=x,q[22],val=0;
flag=true;
q[++val]=8;
if(x!=1)q[++val]=done[x];
while(pre[now]!=0)
{
now=pre[now];
if(done[now]!=0)
{
q[++val]=done[now];
}
}
for(int t=val;t>=1;t--) cout<<q[t]<<' ';
}
if(!p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]])
{
p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]]=true;
tail++;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
f[tail][t][h]=a[t][h];
}
}
pre[tail]=x,done[tail]=8;
}
}
void work9(int x)
{
int a[4][4];
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
a[t][h]=f[x][t][h];
}
}
a[2][2]=add(a[2][2]);
a[2][3]=add(a[2][3]);
a[3][2]=add(a[3][2]);
a[3][3]=add(a[3][3]);
bool fuck=true;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
if(a[t][h]!=3)
{
fuck=false;
break;
}
}
if(fuck==false) break;
}
if(fuck==true)
{
int now=x,q[22],val=0;
flag=true;
q[++val]=9;
if(x!=1)q[++val]=done[x];
while(pre[now]!=0)
{
now=pre[now];
if(done[now]!=0)
{
q[++val]=done[now];
}
}
for(int t=val;t>=1;t--) cout<<q[t]<<' ';
}
if(!p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]])
{
p[a[1][1]][a[1][2]][a[1][3]][a[2][1]][a[2][2]][a[2][3]][a[3][1]][a[3][2]][a[3][3]]=true;
tail++;
for(int t=1;t<=3;++t)
{
for(int h=1;h<=3;++h)
{
f[tail][t][h]=a[t][h];
}
}
pre[tail]=x,done[tail]=9;
}
}
int main()
{
int bb;
memset(p,false,sizeof(p));
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
scanf("%d",&bb);
num[i][j]=bb/3-1;
}
}
p[num[1][1]][num[1][2]][num[1][3]][num[2][1]][num[2][2]][num[2][3]][num[3][1]][num[3][2]][num[3][3]]=true;
head=0,tail=1,pre[tail]=0,done[tail]=0;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
f[tail][i][j]=num[i][j];
}
}
while(head<tail)
{
head++;
work1(head);
if(flag==true) break;
work2(head);
if(flag==true) break;
work3(head);
if(flag==true) break;
work4(head);
if(flag==true) break;
work5(head);
if(flag==true) break;
work6(head);
if(flag==true) break;
work7(head);
if(flag==true) break;
work8(head);
if(flag==true) break;
work9(head);
if(flag==true) break;
}
return 0;
}
500行的代码不知道他是以怎样的毅力打完的。。。
反正我是看着都晕。。
下面是标准std算法:
STD.CPP
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
using namespace std;
#define MAXSTEPS 30
const int a[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 now[9],minstep;
int path[MAXSTEPS],time[9];
int init()
{
int i,k;
for(i=0; i<9; i++)
{
scanf("%d",&k);;
now[i]=(k/3)%4;
}
memset(path,0,sizeof(path));
memset(time,0,sizeof(time));
}
int ok()
{
int i;
for(i=0; i<9; i++)
if(now[i]%4!=0)return 0;
return 1;
}
void output()
{
int i;
for(i=0;i<minstep-1;i++)
cout<<path[i]+1<<" ";
cout<<path[minstep-1]+1<<endl;
}
void change(int i)
{
int j;
for(j=0; j<9; j++)
now[j]+=a[i][j];
}
void regain(int i)
{
int j;
for(j=0; j<9; j++)
now[j]-=a[i][j];
}
void search(int step)
{
int i,j;
if(step>=MAXSTEPS) return;
if(ok())
{
minstep=step;
output();
return;
}
if (step==0) j=0;
else if(time[path[step-1]]<3) j=path[step-1];
else
j=path[step-1]+1;
for(i=j; i<9; i++)
{
change(i);
time[i]++;
path[step]=i;
search(step+1);
regain(i);
time[i]--;
}
}
int main(void)
{
init();
search(0);
return 0;
}
正片开始 ↓ ↓ ↓
国外某大佬的代码(引用自http://blog.csdn.net/dyllove98/article/details/9002826):
WTF.CPP
//??????ans from web
#include <stdio.h>
int a[9][9]= { {3,3,3,3,3,2,3,2,0},
{2,3,2,3,2,3,1,0,1},
{3,3,3,2,3,3,0,2,3},
{2,3,1,3,2,0,2,3,1},
{2,3,2,3,1,3,2,3,2},
{1,3,2,0,2,3,1,3,2},
{3,2,0,3,3,2,3,3,3},
{1,0,1,3,2,3,2,3,2},
{0,2,3,2,3,3,3,3,3} };
int v[9];
int main() {
int i,j,k;
for (i=0; i<9; i++) {
scanf("%d",&k);
for(j=0; j<9; j++)
v[j]=(v[j]+(4-k/3)*a[i][j])%4;
}
fclose(stdin);
k=0;
for (i=0; i<9; i++)
for (j=0; j<v[i]; j++)
if (!k) { printf("%d",i+1); k=1; }
else printf(" %d",i+1);
printf("\n");
fclose(stdout);
return 0;
}
自己感受一下(T_T)(我则根本没打出来)