の問題6をやっています。
解説の解法3を使おうとしているのですが、実行速度が遅いです。
線形探索版は入力3まで、連想配列版は入力2までしか答えを出せませんでした。
どうすればうまく解けるか教えていただければありがたいです。
C言語の範囲(C++は使わない)でお願いします。
よろしくお願いします。
線形探索版
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define nizi(c,x,y) (c[(y)*20+(x)])
#define c2m(c) ((c)=='J'?0:(c)=='O'?1:(c)=='I'?2:3)
typedef struct {
int max[4];
int puttern[4][11000];
int kosuu[4][11000];
} memoone;
memoone* memo;
int countflags(char[21][21],int,int,int,int,int);
int main(int argc,char* argv[]) {
char infile[255],outfile[255];
FILE* in;
FILE* out;
/*declare values*/
int tate,yoko;
char map[21][21];
int i;
int x,y;
int allflags;
int badflags;
int goodflags;
/*open files*/
sprintf(infile,"%s-in%s.txt",argv[1],argv[2]);
sprintf(outfile,"%s-out%s.txt",argv[1],argv[2]);
in=fopen(infile,"r");
if(in==NULL)return 1;
out=fopen(outfile,"w");
if(out==NULL) {
fclose(in);
return 1;
}
/*do work*/
memo=calloc(20*21,sizeof(memoone));
if(memo==NULL)return 1;
fscanf(in,"%d %d",&tate,&yoko);
for(i=1;i<=tate;i++)fscanf(in,"%s",map[i]);
allflags=1;
for(y=1;y<=tate;y++) {
for(x=0;x<yoko;x++) {
if(map[y][x]=='?')allflags=allflags*3%100000;
}
}
strcpy(map[0],"IIIIIIIIIIIIIIIIIIII");
badflags=countflags(map,0,1,0,yoko,tate+1);
goodflags=allflags-badflags;
if(goodflags<0)goodflags+=100000;
fprintf(out,"%d\n",goodflags);
free(memo);
/*file close*/
fclose(in);
fclose(out);
return 0;
}
int searchputtern(int x,int y,int mozi,int puttern) {
int i;
for(i=0;i<nizi(memo,x,y).max[mozi];i++) {
if(nizi(memo,x,y).puttern[mozi][i]==puttern)return i;
}
return -1;
}
int countflags(char map[21][21],int x,int y,int maeputtern,int mx,int my) {
int i;
int nowputtern;
int ptno;
int results;
int nextx,nexty;
nowputtern=maeputtern>>1;
nowputtern&=~(((x>1?(map[y][x-1]=='O'):x>0?0:(map[y-1][mx-1]=='O'))?0:1)<<(mx-2));
if(x>0 && map[y][x-1]=='J')nowputtern|=1<<(mx-1);
ptno=searchputtern(x,y,c2m(map[y][x]),nowputtern);
if(ptno>=0)return nizi(memo,x,y).kosuu[c2m(map[y][x])][ptno];
results=0;
if(x<mx-1) {
nextx=x+1;
nexty=y;
} else {
nextx=0;
nexty=y+1;
}
if(nexty<my) {
if(map[y][x]!='?') {
if(map[y-1][x]=='J' && map[y-1][x+1]=='O' && map[y][x]=='I')results=0;
else results=countflags(map,nextx,nexty,nowputtern,mx,my);
} else {
map[y][x]='J';
results+=countflags(map,nextx,nexty,nowputtern,mx,my);
map[y][x]='O';
results+=countflags(map,nextx,nexty,nowputtern,mx,my);
if(map[y-1][x]!='J' || map[y-1][x+1]!='O') {
map[y][x]='I';
results+=countflags(map,nextx,nexty,nowputtern,mx,my);
}
map[y][x]='?';
}
} else {
switch(map[y][x]) {
case 'J':
results=1;
break;
case 'O':
results=1;
break;
case 'I':
if(map[y-1][x]!='J' || map[y-1][x+1]!='O')results=1;
break;
case '?':
results=2;
if(map[y-1][x]!='J' || map[y-1][x+1]!='O')results++;
break;
}
}
nizi(memo,x,y).puttern[c2m(map[y][x])]
[nizi(memo,x,y).max[c2m(map[y][x])]]=nowputtern;
nizi(memo,x,y).kosuu[c2m(map[y][x])]
[nizi(memo,x,y).max[c2m(map[y][x])]]=results%100000;
nizi(memo,x,y).max[c2m(map[y][x])]++;
return results%100000;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define nizi(c,x,y) (c[(y)*20+(x)])
#define c2m(c) ((c)=='J'?0:(c)=='O'?1:(c)=='I'?2:3)
typedef struct {
int puttern[4][11000];
int kosuu[4][11000];
int used[4][11000];
} memoone;
memoone* memo;
int countflags(char[21][21],int,int,int,int,int);
int main(int argc,char* argv[]) {
char infile[255],outfile[255];
FILE* in;
FILE* out;
/*declare values*/
int tate,yoko;
char map[21][21];
int i;
int x,y;
int allflags;
int badflags;
int goodflags;
/*open files*/
sprintf(infile,"%s-in%s.txt",argv[1],argv[2]);
sprintf(outfile,"%s-out%s.txt",argv[1],argv[2]);
in=fopen(infile,"r");
if(in==NULL)return 1;
out=fopen(outfile,"w");
if(out==NULL) {
fclose(in);
return 1;
}
/*do work*/
memo=calloc(20*21,sizeof(memoone));
if(memo==NULL)return 1;
fscanf(in,"%d %d",&tate,&yoko);
for(i=1;i<=tate;i++)fscanf(in,"%s",map[i]);
allflags=1;
for(y=1;y<=tate;y++) {
for(x=0;x<yoko;x++) {
if(map[y][x]=='?')allflags=allflags*3%100000;
}
}
strcpy(map[0],"IIIIIIIIIIIIIIIIIIII");
badflags=countflags(map,0,1,0,yoko,tate+1);
goodflags=allflags-badflags;
if(goodflags<0)goodflags+=100000;
fprintf(out,"%d\n",goodflags);
free(memo);
/*file close*/
fclose(in);
fclose(out);
return 0;
}
int searchputtern(int x,int y,int mozi,int puttern) {
int i;
i=puttern%11000;
while(1) {
if(nizi(memo,x,y).used[mozi][i] &&
nizi(memo,x,y).puttern[mozi][i]==puttern)return i;
else if(nizi(memo,x,y).used[mozi][i]==0)return -1;
i=(i+123)%11000;
}
return -1;
}
int countflags(char map[21][21],int x,int y,int maeputtern,int mx,int my) {
int i;
int nowputtern;
int ptno;
int results;
int nextx,nexty;
int index;
nowputtern=maeputtern>>1;
nowputtern&=~(((x>1?(map[y][x-1]=='O'):x>0?0:(map[y-1][mx-1]=='O'))?0:1)<<(mx-2));
if(x>0 && map[y][x-1]=='J')nowputtern|=1<<(mx-1);
ptno=searchputtern(x,y,c2m(map[y][x]),nowputtern);
if(ptno>=0)return nizi(memo,x,y).kosuu[c2m(map[y][x])][ptno];
results=0;
if(x<mx-1) {
nextx=x+1;
nexty=y;
} else {
nextx=0;
nexty=y+1;
}
if(nexty<my) {
if(map[y][x]!='?') {
if(map[y-1][x]=='J' && map[y-1][x+1]=='O' && map[y][x]=='I')results=0;
else results=countflags(map,nextx,nexty,nowputtern,mx,my);
} else {
map[y][x]='J';
results+=countflags(map,nextx,nexty,nowputtern,mx,my);
map[y][x]='O';
results+=countflags(map,nextx,nexty,nowputtern,mx,my);
if(map[y-1][x]!='J' || map[y-1][x+1]!='O') {
map[y][x]='I';
results+=countflags(map,nextx,nexty,nowputtern,mx,my);
}
map[y][x]='?';
}
} else {
switch(map[y][x]) {
case 'J':
results=1;
break;
case 'O':
results=1;
break;
case 'I':
if(map[y-1][x]!='J' || map[y-1][x+1]!='O')results=1;
break;
case '?':
results=2;
if(map[y-1][x]!='J' || map[y-1][x+1]!='O')results++;
break;
}
}
index=nowputtern%11000;
while(1) {
if(nizi(memo,x,y).used[c2m(map[y][x])][index]==0)break;
index=(index+123)%11000;
}
nizi(memo,x,y).puttern[c2m(map[y][x])][index]=nowputtern;
nizi(memo,x,y).kosuu[c2m(map[y][x])][index]=results%100000;
nizi(memo,x,y).used[c2m(map[y][x])][index]=1;
return results%100000;
}