poj2965-poj2965-The Pilots Brothers' refrigerator

本文通过逐步优化从链表实现的队列到循环数组实现的队列,解决了在线评测系统中出现的时间限制超出(TLE)问题。具体包括减少状态改变时的计算开销,并采用更高效的队列实现方式。

方法同poj1753,但用在这题就TLE了,以下是TLE版本:


ContractedBlock.gif ExpandedBlockStart.gif Code
  1#include <stdio.h>
  2#include <stdlib.h>
  3#include <string.h>
  4#define MAXSTATE 65536
  5#define MAXSIZE 16
  6#define ALLOPEN 0
  7
  8//队列结构体
  9ExpandedBlockStart.gifContractedBlock.giftypedef struct node{
 10    int data;
 11    struct node *next;
 12}
NODE;
 13ExpandedBlockStart.gifContractedBlock.giftypedef struct{
 14    NODE *front;
 15    NODE *rear;
 16}
QUEUE;
 17//全局变量
 18QUEUE queue;
 19int distance[MAXSTATE];
 20int position[MAXSTATE];
 21int parentState[MAXSTATE];
 22//入队列函数
 23void EnQueue(QUEUE *q, int d)
 24ExpandedBlockStart.gifContractedBlock.gif{
 25    NODE *newNode;
 26    newNode=(NODE *)malloc(sizeof(NODE));
 27    newNode->data=d;
 28    newNode->next=NULL;
 29    
 30ExpandedSubBlockStart.gifContractedSubBlock.gif    if(q->front!=NULL){
 31        q->rear->next=newNode;
 32        q->rear=newNode;
 33    }

 34    else
 35        q->front=q->rear=newNode;
 36}

 37//出队列函数
 38int DeQueue(QUEUE *q)
 39ExpandedBlockStart.gifContractedBlock.gif{
 40    int temp;
 41    NODE *oldNode;
 42ExpandedSubBlockStart.gifContractedSubBlock.gif    if(q->front==NULL){
 43        printf("List empty!\n");
 44        return -1;
 45    }

 46    oldNode=q->front;
 47    temp=q->front->data;
 48    q->front=q->front->next;
 49    free(oldNode);
 50    return temp;
 51}

 52//判断队列是否为空
 53ExpandedBlockStart.gifContractedBlock.gifint Empty(QUEUE *q){
 54    if(q->front==NULL)
 55        return 1;
 56    return 0;
 57}

 58
 59int ChangeState(int id, int pos)
 60ExpandedBlockStart.gifContractedBlock.gif{
 61    int t, new_id;
 62    new_id=id^1<<pos;
 63ExpandedSubBlockStart.gifContractedSubBlock.gif    if (pos>=4){
 64        t=pos-4;
 65ExpandedSubBlockStart.gifContractedSubBlock.gif        while(t>=0{
 66            new_id^=1<<t;
 67            t-=4;
 68        }

 69    }

 70ExpandedSubBlockStart.gifContractedSubBlock.gif    if(pos<=11){
 71        t=pos+4;
 72ExpandedSubBlockStart.gifContractedSubBlock.gif        while(t<=15){
 73            new_id^=1<<t;
 74            t+=4;
 75        }

 76    }

 77ExpandedSubBlockStart.gifContractedSubBlock.gif    if(pos%4>0){//向左
 78        t=pos-1;
 79ExpandedSubBlockStart.gifContractedSubBlock.gif        while(t%4!=3 && t>=0){
 80            new_id^=1<<t;
 81            --t;
 82        }

 83    }

 84ExpandedSubBlockStart.gifContractedSubBlock.gif    if(pos%4<3){//向右
 85        t=pos+1;
 86ExpandedSubBlockStart.gifContractedSubBlock.gif        while(t%4!=0){
 87            new_id^=1<<t;
 88            ++t;
 89        }

 90    }

 91    return new_id;
 92}

 93
 94void Output(int stat)
 95ExpandedBlockStart.gifContractedBlock.gif{
 96    int cur_state, len=0, i;
 97    int arr_x[MAXSIZE];
 98    int arr_y[MAXSIZE];
 99    
100    cur_state=stat;
101    printf("%d\n", distance[cur_state]);
102ExpandedSubBlockStart.gifContractedSubBlock.gif    while(distance[cur_state]!=0){
103        arr_x[len]=position[cur_state]/4+1;
104        arr_y[len++]=position[cur_state]%4+1;
105        cur_state=parentState[cur_state];
106    }

107ExpandedSubBlockStart.gifContractedSubBlock.gif    for (i=len-1;i>=0;i--){
108        printf("%d %d\n", arr_x[i], arr_y[i]);
109    }

110}

111
112void main(int argc, char *argv[])
113ExpandedBlockStart.gifContractedBlock.gif{
114    char c;
115    int cur_state=0, new_state;
116    int i=0;
117    QUEUE *q;
118    q=&queue;
119    //freopen("input.txt", "r", stdin);
120    
121ExpandedSubBlockStart.gifContractedSubBlock.gif    while(scanf("%c"&c)!=EOF){
122ExpandedSubBlockStart.gifContractedSubBlock.gif        if(c!='\n'){
123            if (c=='+') cur_state += 1<<i;
124            i++;
125        }

126    }

127    memset(distance, -1, MAXSTATE*sizeof(int));
128    
129ExpandedSubBlockStart.gifContractedSubBlock.gif    if(cur_state==ALLOPEN){
130        printf("0\n");
131        return;
132    }

133    parentState[cur_state]=-1;
134    distance[cur_state]=0;
135    position[cur_state]=-1;
136    EnQueue(q, cur_state);
137ExpandedSubBlockStart.gifContractedSubBlock.gif    while(!Empty(q)){
138        cur_state=DeQueue(q);
139ExpandedSubBlockStart.gifContractedSubBlock.gif        for (i=0;i<MAXSIZE;i++){
140            new_state=ChangeState(cur_state, i);
141ExpandedSubBlockStart.gifContractedSubBlock.gif            if (new_state==ALLOPEN){//成功
142                parentState[new_state]=cur_state;
143                position[new_state]=i;
144                distance[new_state]=distance[cur_state]+1;
145                Output(new_state);
146                return;
147            }

148ExpandedSubBlockStart.gifContractedSubBlock.gif            if (distance[new_state]==-1){//未访问过结点
149                distance[new_state]=distance[cur_state]+1;
150                position[new_state]=i;
151                parentState[new_state]=cur_state;
152                EnQueue(q, new_state);
153            }

154        }

155    }

156}

 

 优化过程:将需要改变的状态存放在一个一维数组当中,这样就减少了每次改变状态时的开销。如下所示:

int state[MAXSIZE]={
0xF888,0xF444,0xF222,0xF111,
0x8F88,0x4F44,0x2F22,0x1F11,
0x88F8,0x44F4,0x22F2,0x11F1,

0x888F,0x444F,0x222F,0x111F};

 0xF888转换为二进制是1111 1000 1000 1000,换一种格式:

1111

1000

1000

1000

表示改变坐标(0,0)的状态时第一列和第一行的状态都要改变,这样只要和当前状态XOR一下就可以得到新的状态了。

再次提交了一次任然是TLE。。。看来效果不是很明显。

继续改进,发现队列用的是链表实现,效率没有用数组高,因而将链表用数组全部重写。

再次提交,果然AC了。

Run IDUserProblemResultMemoryTimeLanguageCode LengthSubmit Time
4856540zen_chou2965Accepted1220K219MSC2387B2009-03-26 17:27:36

 

ContractedBlock.gif ExpandedBlockStart.gif Code
  1#include <stdio.h>
  2#include <stdlib.h>
  3#include <string.h>
  4#define MAXSTATE 65536
  5#define MAXSIZE 16
  6#define ALLOPEN 0
  7//循环队列结构体
  8ExpandedBlockStart.gifContractedBlock.giftypedef struct{
  9    int head, tail;
 10    int node[MAXSTATE];
 11}
QUEUE;
 12//队列函数
 13void Init(QUEUE *q)
 14ExpandedBlockStart.gifContractedBlock.gif{
 15    q->head=q->tail=0;
 16}

 17int Empty(QUEUE *q)
 18ExpandedBlockStart.gifContractedBlock.gif{
 19    if ((q->head-q->tail)==0return 1;
 20    return 0;
 21}

 22void EnQueue(QUEUE *q ,int d)
 23ExpandedBlockStart.gifContractedBlock.gif{
 24ExpandedSubBlockStart.gifContractedSubBlock.gif    if ((q->tail+1)%MAXSTATE==q->head){
 25        printf("Overflow!\n");
 26        return;
 27    }

 28    q->node[q->tail]=d;
 29    q->tail=(q->tail+1)%MAXSTATE;
 30}

 31int DeQueue(QUEUE *q)
 32ExpandedBlockStart.gifContractedBlock.gif{
 33    int d;
 34ExpandedSubBlockStart.gifContractedSubBlock.gif    if (q->head==q->tail) {
 35        printf("Underflow!\n");
 36        return -1;
 37    }

 38    d=q->node[q->head];
 39    q->head=(q->head+1)%MAXSTATE;
 40    return d;
 41}

 42//全局变量
 43int distance[MAXSTATE];
 44int position[MAXSTATE];
 45int parentState[MAXSTATE];
 46QUEUE queue;
 47ExpandedBlockStart.gifContractedBlock.gifint state[MAXSIZE]={
 480xF888,0xF444,0xF222,0xF111,
 490x8F88,0x4F44,0x2F22,0x1F11,
 500x88F8,0x44F4,0x22F2,0x11F1,
 510x888F,0x444F,0x222F,0x111F}
;
 52
 53
 54int ChangeState(int id, int pos)
 55ExpandedBlockStart.gifContractedBlock.gif{
 56    int new_id;
 57    new_id=id^state[pos];
 58    return new_id;
 59}

 60
 61void Output(int stat)
 62ExpandedBlockStart.gifContractedBlock.gif{
 63    int cur_state, len=0, i;
 64    int arr_x[MAXSIZE];
 65    int arr_y[MAXSIZE];
 66    cur_state=stat;
 67    printf("%d\n", distance[cur_state]);
 68ExpandedSubBlockStart.gifContractedSubBlock.gif    while(distance[cur_state]!=0){
 69        arr_x[len]=position[cur_state]/4+1;
 70        arr_y[len++]=position[cur_state]%4+1;
 71        cur_state=parentState[cur_state];
 72    }

 73ExpandedSubBlockStart.gifContractedSubBlock.gif    for (i=len-1;i>=0;i--){
 74        printf("%d %d\n", arr_x[i], arr_y[i]);
 75    }

 76}

 77
 78void main(int argc, char *argv[])
 79ExpandedBlockStart.gifContractedBlock.gif{
 80    char c;
 81    int cur_state=0, new_state;
 82    int i=0;
 83    QUEUE *q;
 84    q=&queue;
 85    //freopen("input.txt", "r", stdin);
 86    
 87ExpandedSubBlockStart.gifContractedSubBlock.gif    while(scanf("%c"&c)!=EOF){
 88ExpandedSubBlockStart.gifContractedSubBlock.gif        if(c!='\n'){
 89            cur_state<<=1;
 90            if (c=='+') cur_state+=1;
 91        }

 92    }

 93    memset(distance, -1, MAXSTATE*sizeof(int));
 94    
 95ExpandedSubBlockStart.gifContractedSubBlock.gif    if(cur_state==ALLOPEN){
 96        printf("0\n");
 97        return;
 98    }

 99    parentState[cur_state]=-1;
100    distance[cur_state]=0;
101    position[cur_state]=-1;
102    EnQueue(q, cur_state);
103ExpandedSubBlockStart.gifContractedSubBlock.gif    while(!Empty(q)){
104        cur_state=DeQueue(q);
105ExpandedSubBlockStart.gifContractedSubBlock.gif        for (i=0;i<MAXSIZE;i++){
106            new_state=ChangeState(cur_state, i);
107ExpandedSubBlockStart.gifContractedSubBlock.gif            if (new_state==ALLOPEN){//成功
108                parentState[new_state]=cur_state;
109                position[new_state]=i;
110                distance[new_state]=distance[cur_state]+1;
111                Output(new_state);
112                return;
113            }

114ExpandedSubBlockStart.gifContractedSubBlock.gif            if (distance[new_state]==-1){//未访问过结点
115                distance[new_state]=distance[cur_state]+1;
116                position[new_state]=i;
117                parentState[new_state]=cur_state;
118                EnQueue(q, new_state);
119            }

120        }

121    }

122}

转载于:https://www.cnblogs.com/zen_chou/archive/2009/03/26/1422148.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值