HDOJ 1732 Push Box
推箱子,一共有三个箱子,没想出什么特别的方法,就直接用了盲目广搜了。写了很久-_-除了大数模板外我写的最长的一道题目了吧,刚开始RE,hash的时候没处理好,再检查了一下小错误,居然就过掉了……我还以为这道题起码还要搞掉我两天,RP还行。
我是用坐标来储存结点状态,一共6个坐标,每个3位,不过箱子的实际状态比这个要小很多,因为箱子所在的点是不能重复的,大概5000的数组就够用了。
中间还加了个剪枝,就是剪掉有某个点旁边已经有相邻两处被堵死的情况,这个剪枝优化还是比较明显的。
贴下代码:
- #include <iostream>
- using namespace std;
- #define MAX 500000
- #define HF 5555
- int dir[4][2]={{0, 1}, {-1, 0}, {0, -1}, {1, 0}};
- int END, n, m;
- char ma[8][10];
- int hash[8][8][HF];
- struct box{
- int i;
- int j;
- };
- box bo[3], ho[3];
- struct node{
- int ni;
- int nj;
- int t;
- int sta;
- };
- node now, next;
- node qq[MAX];
- inline bool valid(const node &x)
- {
- return (x.ni>=0 && x.nj>= 0 && x.ni<n && x.nj<m);
- }
- inline bool valid(const box &x)
- {
- return (x.i>=0 && x.j>=0 && x.i<n && x.j<m);
- }
- inline bool cmp(const box &x,const box &y)
- {
- if(x.i == y.i)
- return x.j < y.j;
- else return x.i < y.i;
- }
- inline void st(box x[])
- {
- box tmp;
- if(!cmp(x[0], x[1]))
- {
- tmp = x[0];
- x[0] = x[1];
- x[1] = tmp;
- }
- if(!cmp(x[0], x[2]))
- {
- tmp = x[0];
- x[0] = x[2];
- x[2] = tmp;
- }
- if(!cmp(x[1], x[2]))
- {
- tmp = x[1];
- x[1] = x[2];
- x[2] = tmp;
- }
- }
- void init()
- {
- int i;
- now.sta = 0;
- now .t = 0;
- for(i = 0; i < 3; i++)
- {
- now.sta <<= 3;
- now.sta += bo[i].i;
- now.sta <<= 3;
- now.sta += bo[i].j;
- }
- st(ho); END = 0;
- for(i = 0; i < 3; i++)
- {
- END <<= 3;
- END += ho[i].i;
- END <<= 3;
- END += ho[i].j;
- }
- }
- inline bool dead(int x)
- {
- int i, j, k;
- bool c[4];
- box tmp;
- for(i = 0; i < 3; i++)
- {
- bo[i].j = x%8;
- x >>= 3;
- bo[i].i = x%8;
- x >>= 3;
- }
- for(i = 0; i < 3; i++)
- {
- if(ma[bo[i].i][bo[i].j] == '@') continue;
- for(k = 0; k < 4; k++)
- c[k] = 0;
- for(j = 0; j < 4; j++)
- {
- tmp.i = bo[i].i + dir[j][0];
- tmp.j = bo[i].j + dir[j][1];
- if(!valid(tmp))
- c[j] = 1;
- else if(ma[tmp.i][tmp.j] == '#')
- c[j] = 1;
- else {
- for(k = 0; k < 3; k++)
- {
- if(k == i) continue;
- if((bo[i].i == bo[k].i) && (bo[i].j == bo[k].j))
- {
- c[j] = 1;
- break;
- }
- }
- }
- }
- for(j = 0; j < 4; j++)
- if(c[j] == 1)
- {
- k = j + 1;
- if(k == 4) k=0;
- if(c[k] == 1)
- return true;
- }
- }
- return false;
- }
- inline int bfs()
- {
- int flag, vfun;
- box tmp;
- int low = 0, high = 0, i, j;
- memset(hash, -1, sizeof(hash));
- qq[high++] = now;
- hash[now.ni][now.nj][now.sta % HF] = now.sta;
- while(low < high)
- {
- now = qq[low++];
- if(now.sta == END) return now.t;
- if(low >= MAX) low %= MAX;
- for(i = 0; i < 4; i++)
- {
- next.ni = now.ni + dir[i][0];
- next.nj = now.nj + dir[i][1];
- if(dead(now.sta)) continue;
- if(!valid(next) || ma[next.ni][next.nj] == '#') continue;
- next.sta = now.sta;
- flag = -1;
- for(j = 0; j < 3 && flag == -1; j++)
- {
- bo[j].j = next.sta % 8;
- next.sta >>= 3;
- bo[j].i = next.sta % 8;
- next.sta >>= 3;
- if(bo[j].i == next.ni && bo[j].j == next.nj)
- flag = j;
- }
- if(flag == -1)
- {
- next.sta = now.sta;
- vfun = next.sta % HF;
- while(hash[next.ni][next.nj][vfun] != -1 && hash[next.ni][next.nj][vfun] != next.sta)
- {
- vfun+=7;
- if(vfun >= HF) vfun %= HF;
- }
- if(hash[next.ni][next.nj][vfun] == next.sta) continue;
- else
- hash[next.ni][next.nj][vfun] = next.sta;
- next.t = now .t + 1;
- qq[high++] = next;
- if(high >= MAX) high %= MAX;
- }
- else {
- tmp.i = next.ni + dir[i][0];
- tmp.j = next.nj + dir[i][1];
- if(!valid(tmp) || ma[tmp.i][tmp.j] == '#') continue;
- for(j = 0; j < 3; j++)
- {
- if(flag == j) continue;
- if(tmp.i == bo[j].i && tmp.j == bo[j].j)
- {
- flag = -1; break;
- }
- }
- if(flag == -1) continue;
- else {
- bo[flag].i = tmp.i;
- bo[flag].j = tmp.j;
- st(bo);
- next.sta = 0;
- for(j = 0; j < 3; j++)
- {
- next.sta <<= 3;
- next.sta += bo[j].i;
- next.sta <<= 3;
- next.sta += bo[j].j;
- }
- vfun = next.sta % HF;
- while(hash[next.ni][next.nj][vfun] != -1 && hash[next.ni][next.nj][vfun] != next.sta)
- {
- vfun+=7;
- if(vfun >= HF) vfun %=HF;
- }
- if(hash[next.ni][next.nj][vfun] == next.sta) continue;
- else {
- hash[next.ni][next.nj][vfun] = next.sta;
- }
- next.t = now.t + 1;
- qq[high++] = next;
- if(high >= MAX) high %= MAX;
- }
- }
- }
- }
- return -1;
- }
- int main()
- {
- int i, j;
- int cb, ch, ret;
- while(scanf("%d %d", &n, &m)!= EOF)
- {
- getchar();
- cb = 0; ch = 0;
- for(i = 0; i < n; i++)
- {
- gets(ma[i]);
- for(j = 0; j < m; j++)
- {
- if(ma[i][j] == '@')
- {
- ho[ch].i = i;
- ho[ch++].j = j;
- }
- else if(ma[i][j] == '*')
- {
- bo[cb].i = i;
- bo[cb++].j = j;
- ma[i][j] = '.';
- }
- else if(ma[i][j] == 'X')
- {
- now.ni = i;
- now.nj = j;
- ma[i][j] = '.';
- }
- }
- }
- init();
- ret = bfs();
- printf("%dn", ret);
- }
- return 0;
- }
HDOJ 1401
Solitaire,比较单纯的双广,考虑了下怎么保存棋子的状态,然后直接开搜. MS别人都是用两个queue来做的……
第一次写双广,效率不是很高。
一共有四个棋子,一个坐标需要3位来存,这是数是蛮大的,但实际状态64万就够用了,普通的hash能够搞定。
贴下代码:
- #include <iostream>
- #include <queue>
- using namespace std;
- #define MAX 235536
- int h[MAX];
- int v[MAX];
- int dir[4][2]={0,1,-1,0,0,-1,1,0};
- struct chess{
- int i;
- int j;
- };
- struct pos{
- chess c[4];
- int sta;
- int t;
- int fl;
- };
- queue <pos> ch;
- pos s,e,now,next;
- inline bool cmp(const chess x,const chess y)
- {
- if(x.i==y.i) return x.j<y.j;
- else return x.i<y.i;
- }
- inline bool valid(chess x)
- {
- return (x.i>=0 && x.j>=0 && x.i<8 && x.j<8);
- }
- inline int encode(pos x)
- {
- int i;
- int sta=0;
- sort(x.c, x.c+4, cmp);
- for(i=0;i<4;i++)
- {
- sta<<=3;
- sta+=x.c[i].i;
- sta<<=3;
- sta+=x.c[i].j;
- }
- return sta;
- }
- inline bool bfs()
- {
- int i,j,k,t,l;
- bool flag;
- memset(h,-1,sizeof(h));
- memset(v,-1,sizeof(v));
- while(!ch.empty()) ch.pop();
- s.t=0; s.fl=1;
- s.sta=encode(s);
- e.t=0; e.fl=2;
- e.sta=encode(e);
- if(s.sta == e.sta) return true;
- t=s.sta%MAX;
- while(h[t]!=-1 && v[t]!=s.sta){
- t+=10;
- if(t>=MAX) t%=MAX;
- }
- h[t]=s.fl; v[t]=s.sta;
- t=e.sta%MAX;
- while(h[t]!=-1 && v[t]!=s.sta){
- t+=10;
- if(t>=MAX) t%=MAX;
- }
- h[t]=e.fl; v[t]=e.sta;
- ch.push(s); ch.push(e);
- while(!ch.empty()){
- now=ch.front(); ch.pop();
- if(now.t>3) continue;
- for(i=0;i<4;i++){
- for (j=0;j<4;j++){
- next.c[j].i=now.c[j].i;
- next.c[j].j=now.c[j].j;
- }
- for(j=0;j<4;j++){
- if(j){
- next.c[j-1].i=now.c[j-1].i;
- next.c[j-1].j=now.c[j-1].j;
- }
- next.c[j].i+=dir[i][0];
- next.c[j].j+=dir[i][1];
- if(!valid(next.c[j])) continue;
- flag=0;
- for(k=0;k<4 && !flag;k++){
- if(j==k) continue;
- if(next.c[j].i==next.c[k].i && next.c[j].j==next.c[k].j)
- flag=1;
- }
- if(!flag){
- next.sta=encode(next);
- next.fl=now.fl;
- t=next.sta%MAX;
- while(h[t]!=-1 && v[t]!=next.sta){
- t+=10;
- if(t>=MAX) t%=MAX;
- }
- if(v[t]==next.sta) {
- if(h[t]!=next.fl) return true;
- else continue;
- }
- else {
- next.t=now.t+1;
- if(next.t>4) continue;
- h[t]=next.fl;
- v[t]=next.sta;
- ch.push(next);
- }
- }
- else {
- next.c[j].i+=dir[i][0];
- next.c[j].j+=dir[i][1];
- if(!valid(next.c[j])) continue;
- flag=0;
- for(k=0;k<4 && !flag;k++){
- if(j==k) continue;
- if(next.c[j].i==next.c[k].i && next.c[j].j==next.c[k].j)
- flag=1;
- }
- if(flag) continue;
- else {
- next.fl=now.fl;
- next.sta=encode(next);
- t=next.sta%MAX;
- while(h[t]!=-1 && v[t]!=next.sta){
- t+=10;
- if(t>=MAX) t%=MAX;
- }
- if(v[t]==next.sta) {
- if(h[t]!=next.fl) return true;
- else continue;
- }
- else {
- next.t=now.t+1;
- if(next.t>4) continue;
- h[t]=next.fl;
- v[t]=next.sta;
- ch.push(next);
- }
- }
- }
- }
- }
- }
- return false;
- }
- int main()
- {
- int i;
- bool ret;
- while(scanf("%d",&s.c[0].i)!=EOF){
- scanf("%d",&s.c[0].j);
- for(i=1;i<4;i++)
- scanf("%d %d",&s.c[i].i,&s.c[i].j);
- for(i=0;i<4;i++)
- scanf("%d %d",&e.c[i].i,&e.c[i].j);
- for(i=0;i<4;i++)
- {
- s.c[i].i--;s.c[i].j--;
- e.c[i].i--;e.c[i].j--;
- }
- ret=bfs();
- if(ret) printf("YESn");
- else printf("NOn");
- }
- return 0;
- }
HDOJ 1180
诡异的楼梯,一道蛮单纯的广搜题,不过我觉得有些细节还是比较值得注意的(我忽略了过楼梯后的若干情况)。
相对其他换汤不换药的迷宫来说,蛮有意思。
- #include <iostream>
- #include <queue>
- using namespace std;
- char ma[22][22];
- int hash[22][22];
- int dir[4][2]={0,1,-1,0,0,-1,1,0};
- int n,m;
- struct node{
- int ni;
- int nj;
- int t;
- };
- node now,next;
- priority_queue <node> hp;
- inline bool operator<(const node &x,const node &y)
- {
- return x.t>y.t;
- }
- inline bool valid(const node &x)
- {
- return (x.ni>=0 && x.nj>=0 && x.ni<n && x.nj<m);
- }
- inline int bfs()
- {
- int i;
- int sd;
- while(!hp.empty()) hp.pop();
- memset(hash,0,sizeof(hash));
- hash[now.ni][now.nj]=1;
- hp.push(now);
- while(!hp.empty())
- {
- now=hp.top();hp.pop();
- if(ma[now.ni][now.nj]=='T')
- return now.t;
- for(i=0;i<4;i++)
- {
- next.ni=now.ni+dir[i][0];
- next.nj=now.nj+dir[i][1];
- if(!valid(next) || ma[next.ni][next.nj]=='*') continue;
- if(hash[next.ni][next.nj]) continue;
- if(ma[next.ni][next.nj]=='T' || ma[next.ni][next.nj]=='.')
- {
- next.t=now.t+1;
- hp.push(next);
- hash[next.ni][next.nj]=1;
- continue;
- }
- if(ma[next.ni][next.nj]=='-' && (i&1)==0)
- sd=1;
- else if(ma[next.ni][next.nj]=='|' && (i&1)==1)
- sd=1;
- else sd=0;
- next.ni+=dir[i][0];
- next.nj+=dir[i][1];
- if(!valid(next) || ma[next.ni][next.nj]=='*') continue;
- if(hash[next.ni][next.nj]) continue;
- if(((now.t&1)==0 && sd==1) || ((now.t&1)==1 && sd==0))
- next.t=now.t+1;
- else
- next.t=now.t+2;
- hash[next.ni][next.nj]=1;
- hp.push(next);
- }
- }
- return 0;
- }
- int main()
- {
- bool flag;
- int i,j,ret;
- while(scanf("%d %d",&n,&m)!=EOF)
- {
- getchar(); flag=0;
- for(i=0;i<n;i++)
- {
- gets(ma[i]);
- for(j=0;j<m && !flag;j++)
- if(ma[i][j]=='S'){
- now.ni=i;
- now.nj=j;
- now.t=0;
- flag=1;
- }
- }
- ret=bfs();
- printf("%dn",ret);
- }
- return 0;
- }
我真搓
这两场比赛都很郁闷,感觉像梦游,而且都是刚好在这两场加权的网络赛上。- -!
其他队员经过一个暑假集训都成长了好多,但我却好像根本没什么进步,现在也许我是整个集训队最弱的队员吧。记得暑假刚开始,lcy老师曾经在论坛里发贴跟我说:高手都是要以题量为保证的,指出我做题的数量太少。那时候我也听进去了,但心里总还有一点觉得我被刘老师给bs了。今天想想,觉得其实完全不是那样的,正是因为对我抱有期望所以才来指出我的短处啊。唉~~暑假都结束一个月了,可以看看我的这三个月来,只做了那么点题目,专题的跟进更是不行,跟托蒂简直不能比,太可怜啦。。
自从被szm指责后,我已经改掉了老喜欢发表决心的毛病了。但我觉得这次真的有必要下一次决心,要把以前落下的都一样一样补上!
08-9-27
非常舒服的天气,也许是lcd盯太久了,偶尔抬头看天,就会有一种刺眼+震撼的感觉。那种湛蓝的颜色以及从视线边际射过来的光线让我不得不眯着眼睛,但是又充斥着就这么一直看下去的欲望。
是不是说明我真的变成一个宅男啦。
不知道为什么,如果被室外的风吹到有点凉意的时候,就会不由自主回忆起很多小时候的事情。且第一个闪过的画面总是自己趴在窗户边羡慕那些在楼下嬉戏的小孩,因为那时的我就很懒,总是不爱做作业所以老被老妈关在家里;那时候从窗外冲进来的风印象中就是这么带着点低温的伤感的。而后就是想起小学时老爸老妈常常带着我出去郊游的情景,低年级的我还是很乖的,每次都很快的把作文以外作业完成,然后星期天就可以出去郊游啦,我总是手里拿着一份树枝在行人踏出的小路上跑来跑去,并且去抽那些路边的野草。因为郊游大部分都在春天和秋天出去,地点也都在山上或者水边,那时候的风也是凉飕飕的。那时候应该还留下了蛮多照片的,不过我从高中后好像就没有去看过了,也许老爸老妈还偶尔会翻一下吧。
长大到底是好还是坏,很难说啊……









