参考:
http://blog.tomtung.com/2007/02/usaco-p58-the-clocks/
BFS 算法(没看出来)
本地测试通过,USACO上报错; 粘了原版的代码,报同样的错
> Run 1: Execution error: Your program exited with exit status
`127'.
------ Data for Run 1 [length=19 bytes] ------
9 9 12
6 6 6
6 3 6
----------------------------
Your program printed data to stderr. Here is the data:
-------------------
program:_error_while_loading_shared_libraries:_libm.so.6:_failed_to_map_segment_from_shared_object:_Cannot_allocate_memory
-------------------
/*
ID: nenusb1
LANG: C++
TASK: clocks
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct{
char Time[11];//九个钟表的状态 ,取值为:0,1,2,3
char num[28];//记录到达该节点的各个操作编号,最多需9*3 = 27
char depth;//深度i表示下一个节点要记录的操作编号位置,即num[0]~num[i]是下一个节点的操作序列;
char operate_times[10]; //operate_times[i]的值为已经进行i操作的次数
//避免同一操作序列由于顺序不同造成的节点重复
char operation;//当前操作号i,除根节点外,表示当前节点是由前一个节点经过i操作产生的
}Clock;
Clock Clocks[262144];
const char operate[][6] = { /*每个操作影响的钟表号,每个操作的序列以-1结尾,省得要检查所有9个钟表*/
{0,0,0,0,0,0},//下标从1 开始
{1,2,4,5,-1},//操作1
{1,2,3,-1} ,//操作2
{2,3,5,6,-1},
{1,4,7,-1},
{2,4,5,6,8,-1},
{3,6,9,-1},
{4,5,7,8,-1},
{7,8,9,-1},
{5,6,8,9,-1}
};
int main(){
freopen("clocks.in","r",stdin);
freopen("clocks.out","w",stdout);
int i,j,k;
Clocks[0].Time[0] = '0';
for(i=1; i<=9; i++){
int temp;
scanf("%d",&temp);
Clocks[0].Time[i] = (temp%12)/3 + '0';//+'0'转为char
}
Clocks[0].Time[10] = '\0';
Clocks[0].operation = '1';//方便生成第一个节点时 从操作1 开始
Clocks[0].depth = '0';
memset(Clocks[0].operate_times, 0,sizeof(Clocks[0].operate_times)); //注意是0不是'0'
memset(Clocks[0].num,0,sizeof(Clocks[0].num));
//需要两个指针
//pre 初始为根节点,cur为其子节点
//每次根据pre节点的值 做 9个操作,对应生成9个不同的cur节点,
//若cur节点的Time[]全为0, 则说明已经完成搜索
int pre = 0, cur = 1;
int flag = true;//搜索完成时 设为 false
int depth = 0;//方便测试
while(flag && pre<cur ){ //没理解为什么pre < cur??????? 我猜是以防找不到时仍可以退出循环
// for(i = 1; i<=9; i++){
//为了避免同一操作序列由于顺序不同造成的节点重复,我
//们每次扩展节点时,都只对操作号大于当前操作号的操作进行尝试。
//当前操作号 对应于 Clocks节点的operation属性
//从prev节点的信息 根据不同操作,扩展出不同的cur节点
for(i = (Clocks[pre].operation-'0'); i<=9; i++){
/*如果某操作执行超过3次则取消本次循环*/
if(Clocks[pre].operate_times[i]=='3') continue;
//i 现在代表第i个操作
strcpy(Clocks[cur].Time, Clocks[pre].Time);
j = 0;
int n=operate[i][j] ;//n存储i操作能affect的clock,即Clocks[cur].Time[n]要加1
while( n!=-1 ){
//printf("pre is %c--",Clocks[pre].Time[n]);
Clocks[cur].Time[n] = ((Clocks[pre].Time[n]-'0') + 1)%4 + '0';
j++;
n=operate[i][j];
}
//记录到达该节点的各个操作编号,在前一个节点的基础上,再加一个i操作
strcpy(Clocks[cur].num , Clocks[pre].num);
depth = Clocks[pre].depth-'0';
Clocks[cur].num[depth] = i + '0';
Clocks[cur].depth = (depth + 1) + '0';
//operate_times[i]的值为已经进行i操作的次数 ,则Clocks[cur].operate_times[i]要加1
//strcpy(Clocks[cur].operate_times, Clocks[pre].operate_times);
memcpy(Clocks[cur].operate_times, Clocks[pre].operate_times,sizeof(Clocks[0].operate_times));//为什么用memcpy???
Clocks[cur].operate_times[i] = Clocks[cur].operate_times[i]+1; //不用转int再加1
//避免同一操作序列由于顺序不同造成的节点重复
Clocks[cur].operation = i+'0';
//test
// printf("pre = %d cur=%d\n",pre,cur);
// for(k=1; k<=9; k++){
// printf("for %d pre=%c cur=%c\n ",k,Clocks[pre].Time[k],Clocks[cur].Time[k]);
// }
// int d = Clocks[cur].depth-'0';
// printf("seq is:\n");
// for(k=0; k<d; k++){
// printf("%c-",Clocks[cur].num[k]);
// }
// printf("\n");
//找到了 flag设为false,停止最外围 while循环
for(k=1; k<=9; k++){
if (Clocks[cur].Time[k]!='0') break;
}
if(k == 10) {flag=false; break; }//停止生成子节点for循环
//没找到就继续生成
cur++;
}//for
//printf("%d %d\n",pre,cur);
pre++;
} //while
//printf("%d %d\n",pre,cur);
k = Clocks[cur].depth-'0';
printf("%c", Clocks[cur].num[0]);
for(i=1; i<k; i++){
printf(" %c",Clocks[cur].num[i]);
}
return 0;
}