JOI2010予選 問6のソースコード
#include <cstdio> #include <vector> #include <algorithm> using namespace std; int w,h,n; int kx,ky; int map[20][20]; vector<pair<int,int> > pts; vector<vector<int> > memo; int findnext(int dir,int state,int x,int y) { int dx=0,dy=0; if(dir==0){dy=-1;} if(dir==2){dy=1;} if(dir==1){dx=-1;} if(dir==3){dx=1;} x+=dx;y+=dy; while(0<=x&&x<w&&0<=y&&y<h) { if(map[x][y]>=0&&((state&1<<map[x][y])==0)) { return map[x][y]; } x+=dx;y+=dy; } return -1; } int calc(int state,int id) { if(memo[state][id]>=0){return memo[state][id];} int x=pts[id].first; int y=pts[id].second; if(state == (1<<n)-1) { if(x==kx||y==ky){return 1;} else {return 0;} } int sum=0; int next=-1; if((next=findnext(0,state,x,y))!=-1){sum += calc(state|1<<next,next);} if((next=findnext(1,state,x,y))!=-1){sum += calc(state|1<<next,next);} if((next=findnext(2,state,x,y))!=-1){sum += calc(state|1<<next,next);} if((next=findnext(3,state,x,y))!=-1){sum += calc(state|1<<next,next);} memo[state][next]=sum; return sum; } int main() { int tmp; scanf("%d %d",&w,&h); for(int j=0;j<h;j++) { for(int i=0;i<w;i++) { scanf("%d",&tmp); if(tmp==1) { map[i][j]=pts.size(); pts.push_back(make_pair(i,j)); } else { map[i][j]=-1; if(tmp==2){kx=i;ky=j;} } } } n=pts.size(); memo = vector<vector<int> >(1<<n); for(int i=0;i<1<<n;i++) { for(int j=0;j<n;j++) { memo[i].push_back(-1); } } int result=0; int next=-1; if((next=findnext(0,0,kx,ky))!=-1){result += calc(1<<next,next);} if((next=findnext(1,0,kx,ky))!=-1){result += calc(1<<next,next);} if((next=findnext(2,0,kx,ky))!=-1){result += calc(1<<next,next);} if((next=findnext(3,0,kx,ky))!=-1){result += calc(1<<next,next);} printf("%d\n",result); }
入力データ1での実行結果
$ ./a.exe < in.txt 36 Aborted (core dumped)
これを読んだあなた。どうかAbortedの真相を暴いてください。それだけが私の望みです。
*追記 02/18 22:28
calcの中のmemo[state][next]=sum;が間違っていました。
正しくはmemo[state][id]=sum;
いわゆるメモ化再帰です。…なんでAcceptedだったんだろう?