题目:
拨钟问题
有9个时钟,排成一个3*3的矩阵。
现在需要用最少的移动,将9个时钟的指针都拨到12点的位置。共允许有9种不同的移动。如下表所示,每个移动会将若干个时钟的指针沿顺时针方向拨动90度。
移动 影响的时钟
1 ABDE
2 ABC
3 BCEF
4 ADG
5 BDEFH
6 CFI
7 DEGH
8 GHI
9 EFHI
Input
9个整数,表示各时钟指针的起始位置,相邻两个整数之间用单个空格隔开。其中,0=12点、1=3点、2=6点、3=9点。
Output
输出一个最短的移动序列,使得9个时钟的指针都指向12点。按照移动的序号从小到大输出结果。相邻两个整数之间用单个空格隔开。
Sample Input
3 3 0
2 2 2
2 1 2
Sample Output
4 5 8 9
题意:
有9个钟,每个钟初始只能为0, 1, 2, 3, 其中0代表12点, 1代表3点, 2代表6点, 3代表9点。
有9个操作,每个操作将操作中对应序号的时钟顺时针旋转90度,问题是找出一个操作最少的组合,使得所有的时钟都变为12点。
思路:
对于列表中1到9的某一个操作,可以进行0次、1次、2次、3次,第4次就变回本身。那么一共有4^9次方个组合。可以用9个for循环,也可以用dfs。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
int arr[10];
int vis[10];
int sum[10];
int ans[10];
int minn=0x7FFFFFFF;
using namespace std;
char mp[15][15] ={
"",
"ABDE",
"ABC",
"BCEF",
"ADG",
"BDEFH",
"CFI",
"DEGH",
"GHI",
"EFHI"
};
void dfs(int depth){
if(depth==10){
for(int i=1; i<=9; i++){
if(arr[i]%4!=0){
return;
}
}
int asum = 0;
for(int i=1; i<=9; i++){
asum += sum[i];
}
if(asum<minn){
for(int i=1; i<=9; i++){
if(vis[i]==1){
ans[i] = sum[i];
}
else
ans[i]=0;
}
minn = asum;
}
return;
}
for(int i=0; i<4; i++){
for(int j=0; j<strlen(mp[depth]); j++){
// arr[mp[depth][j]-64] = (arr[mp[depth][j]-64]+3*i)%12;
arr[mp[depth][j]-64] = (arr[mp[depth][j]-64]+i);
}
vis[depth]=(i==0)?0:1;
sum[depth]=i;
dfs(depth+1);
for(int j=0; j<strlen(mp[depth]); j++){
//arr[mp[depth][j]-64] = (arr[mp[depth][j]-64]+12*i-3*i)%12;
arr[mp[depth][j]-64] = (arr[mp[depth][j]-64]-i);
}
vis[depth]=0;
sum[depth]=0;
}
}
int main(){
int tmp;
memset(arr, 0, sizeof(arr));
//freopen("input.txt","r", stdin);
//freopen("output.txt", "w", stdout);
for(int i=1; i<=9; i++){
cin>>tmp;
arr[i] = tmp;
}
dfs(1);
int tag=0;
for(int i=1; i<=9; i++){
if(ans[i]!=0){
for(int j=0; j<ans[i]; j++){
if(tag==0){cout<<i; tag=-1;}
else cout<<" "<<i;
}
}
}
cout<<endl;
return 0;
}
总结:
题意又理解偏了,(汗!--)
输入只可能为0, 1, 2, 3,我以为还有其他的输入。。于是我将0, 1, 2 , 3转化为所对应的实际的点,按理说这样模拟也可以过,但是开始忘记将minn的值进行更新,改了之后还是WA,卡了一个下午,最后问了一下同学,发现又将题意理解错了,于是我按输入只有0, 1, 2, 3来写,过了。我倒回头看原来模拟的写法,漏了指令使用次数为0时的一次模运算!!!
下面贴最开始模拟现实时钟的写法(看错题目的产物):
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
int arr[10];
int vis[10];
int sum[10];
int ans[10];
int minn=0x7FFFFFFF;
using namespace std;
char mp[15][15] ={
"",
"ABDE",
"ABC",
"BCEF",
"ADG",
"BDEFH",
"CFI",
"DEGH",
"GHI",
"EFHI"
};
void dfs(int depth){
if(depth==10){
for(int i=1; i<=9; i++){
if(arr[i]!=0){
return;
}
}
//for(int i=1; i<=9; i++) {cout<<arr[i]<<" "; cout<<endl;}
int asum = 0;
for(int i=1; i<=9; i++){
asum += sum[i];
}
if(asum<minn){
for(int i=1; i<=9; i++){
if(vis[i]==1){
ans[i] = sum[i];
}
else
ans[i]=0;
}
minn = asum;
}
return;
}
for(int i=0; i<4; i++){
for(int j=0; j<strlen(mp[depth]); j++){
arr[mp[depth][j]-64] = (arr[mp[depth][j]-64]+3*i)%12;
}
vis[depth]=(i==0)?0:1;
sum[depth]=i;
dfs(depth+1);
for(int j=0; j<strlen(mp[depth]); j++){
arr[mp[depth][j]-64] = (arr[mp[depth][j]-64]+12*i-3*i)%12;
}
vis[depth]=0;
sum[depth]=0;
}
}
int main(){
int tmp;
memset(arr, 0, sizeof(arr));
//freopen("input.txt","r", stdin);
//freopen("output.txt", "w", stdout);
for(int i=1; i<=9; i++){
cin>>tmp;
if(tmp==0) arr[i]=12;
else if(tmp==1) arr[i]=3;
else if(tmp==2) arr[i]=6;
else if(tmp==3) arr[i]=9;
// else if(tmp==4) arr[i]=12;
// else if(tmp==5) arr[i]=3;
// else if(tmp==6) arr[i]=6;
// else if(tmp==7) arr[i]=9;
// else if(tmp==8) arr[i]=12;
// else if(tmp==9) arr[i]=3;
// else if(tmp==10) arr[i]=6;
// else if(tmp==11) arr[i]=9;
// else arr[i]=12;
}
dfs(1);
int tag=0;
for(int i=1; i<=9; i++){
if(ans[i]!=0){
for(int j=0; j<ans[i]; j++){
if(tag==0){cout<<i; tag=-1;}
else cout<<" "<<i;
}
}
}
cout<<endl;
return 0;
}
写了这题收获很多!!