https://code.google.com/codejam/contest/204113/dashboard#s=p1
小的case是暴搜过的。在一个位置有四种选择,左走,右走,左挖,右挖。
记得刚右走一步之后,不能马上左走,要不死循环了。
一个剪枝是如果当然挖的多余当前最好的解。
#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <stdio.h>
#include <string>
#include <cctype>
#include <ctime>
#include <strstream>
typedef long long ll;
using namespace std;
#define N 55
int R,C,F,ans;
bool ca[N][N];
struct sol
{
int x,y,di,la;//la=-1×ó±ß£¬0ÎÞ£¬1ÓÒ±ß
sol(){};
sol(int _x,int _y,int _d,int _l)
{
x=_x;
y=_y;
di=_d;
la=_l;
}
};
void se(sol c)
{
int i;
if(c.x==R-1)
{
if(c.di<ans)
{
ans=c.di;
}
return;
}
if(c.di>=ans)return;
if(c.y<C-1)
{
if(c.la!=1&&ca[c.x][c.y+1]==0&&ca[c.x+1][c.y+1])se(sol(c.x,c.y+1,c.di,-1));
if(ca[c.x][c.y+1]==0&&ca[c.x+1][c.y+1]==0)
{
i=c.x+2;
while(ca[i][c.y+1]==0)i++;
if(i-c.x-1<=F)se(sol(i-1,c.y+1,c.di,0));
}
if(ca[c.x][c.y+1]==0&&ca[c.x+1][c.y+1])
{
ca[c.x+1][c.y+1]=0;
se(sol(c.x,c.y,c.di+1,0));
ca[c.x+1][c.y+1]=1;
}
}
if(c.y>0)
{
if(c.la!=-1&&ca[c.x][c.y-1]==0&&ca[c.x+1][c.y-1])se(sol(c.x,c.y-1,c.di,1));
if(ca[c.x][c.y-1]==0&&ca[c.x+1][c.y-1]==0)
{
i=c.x+2;
while(ca[i][c.y-1]==0)i++;
if(i-c.x-1<=F)se(sol(i-1,c.y-1,c.di,0));
}
if(ca[c.x][c.y-1]==0&&ca[c.x+1][c.y-1])
{
ca[c.x+1][c.y-1]=0;
se(sol(c.x,c.y,c.di+1,0));
ca[c.x+1][c.y-1]=1;
}
}
}
int main()
{
ios_base::sync_with_stdio(false);
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
int cas;
int ki,i,j;
char ch;
scanf("%d",&cas);
for(ki=1;ki<=cas;ki++)
{
printf("Case #%d: ",ki);
//cin>>R>>C>>F;
scanf("%d%d%d",&R,&C,&F);
for(i=0;i<R;i++)
{
ch=getchar();
for(j=0;j<C;j++)
{
ch=getchar();
if(ch=='.')ca[i][j]=0;
else ca[i][j]=1;
}
}
for(j=0;j<C;j++)
ca[R][j]=1;
ans=99999;
se(sol(0,0,0,0));
if(ans==99999)puts("No");
else printf("Yes %d\n",ans);
fflush(stdout);
}
return 0;
}
大的case是看了解析之后,才做的。看完也想了好久。
我开的是50*50*50*2*2的数组。dp[x][l][r][bl][br]来存储
刚到第x行时,最左可以走到l位置,最右可以走到r位置,bl,br=0表示l或者r处可以落下去,bl,br=1表示l或者r外是墙,l,r处不能落。
发现搜索的顺序,会影响结果:要先搜拆的少的情况,后搜拆的多的。
下面是代码。
#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <stdio.h>
#include <string>
#include <cctype>
#include <ctime>
#include <strstream>
typedef long long ll;
using namespace std;
#define N 55
#define INF 99999
int R,C,F,ans;
bool ca[N][N];
int dp[N][N][N][2][2];
void dis()
{
int i,j;
for(i=0;i<R;i++)
{
for(j=0;j<C;j++)
printf("%d ",ca[i][j]);
puts("");
}
}
int se(int x,int y,int l,int r,bool bl,bool br)//bl==1×ó±ßÊÇǽ£¬0×ó±ßÊÇ¿Õ
{
if(x==R-1)return 0;
if(l==-2)
{
bl=br=1;
for(l=y;l>=0;l--)
{
if(ca[x][l])
{
break;
}
if(!ca[x+1][l])
{
bl=0;
break;
}
}
if(bl)l++;
for(r=y;r<C;r++)
{
if(ca[x][r])
{
break;
}
if(!ca[x+1][r])
{
br=0;
break;
}
}
if(br)r--;
}
if(dp[x][l][r][bl][br]!=-1)return dp[x][l][r][bl][br];
//printf("%d %d %d %d %d %d\n",x,y,l,r,bl,br);
if(bl&&br&&l==r)return dp[x][l][r][bl][br]=INF;
int i,j,k;
set<int> ret;
ret.insert(INF);
if(!bl)
{
i=x+2;
while(ca[i][l]==0)i++;
if(i-x-1<=F)ret.insert(se(i-1,l,-2,0,0,0));
ret.insert(se(x,y,l+1,r,1,br));
for(j=1;l+j<r;j++)
if(ca[x+1][l+j+1])
{
ca[x+1][l+j]=0;
i=x+2;
while(ca[i][l+j]==0)i++;
if(i-x-1<=F)ret.insert(se(i-1,l+j,-2,0,0,0)+j);
}
for(j=1;l+j<r;j++)
ca[x+1][l+j]=1;
}
else if(ca[x+1][l+1])
{
ret.insert(se(x,y,l+1,r,1,br));
ca[x+1][l]=0;
ret.insert(se(x,y,l,r,0,br)+1);
ca[x+1][l]=1;
}
if(!br)
{
i=x+2;
while(ca[i][r]==0)i++;
if(i-x-1<=F)ret.insert(se(i-1,r,-2,0,0,0));
ret.insert(se(x,y,l,r-1,bl,1));
for(j=1;r-j>l;j++)
if(ca[x+1][r-j-1])
{
ca[x+1][r-j]=0;
i=x+2;
while(ca[i][r-j]==0)i++;
if(i-x-1<=F)ret.insert(se(i-1,r-j,-2,0,0,0)+j);
}
for(j=1;r-j>l;j++)
ca[x+1][r-j]=1;
}
else if(ca[x+1][r-1])
{
ret.insert(se(x,y,l,r-1,bl,br));
ca[x+1][r]=0;
ret.insert(se(x,y,l,r,bl,0)+1);
ca[x+1][r]=1;
}
//dis();
//printf("%d %d %d %d %d\t\t%d\n\n",x,l,r,bl,br,*ret.begin());
return dp[x][l][r][bl][br]=*ret.begin();
}
int main()
{
ios_base::sync_with_stdio(false);
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
int cas;
int ki,i,j;
char ch;
scanf("%d",&cas);
for(ki=1;ki<=cas;ki++)
{
printf("Case #%d: ",ki);
//cin>>R>>C>>F;
scanf("%d%d%d",&R,&C,&F);
memset(dp,-1,sizeof(dp));
for(i=0;i<R;i++)
{
ch=getchar();
for(j=0;j<C;j++)
{
ch=getchar();
if(ch=='.')ca[i][j]=0;
else ca[i][j]=1;
}
}
for(j=0;j<C;j++)
ca[R][j]=1;
ans=se(0,0,-2,0,0,0);
if(ans>=INF)puts("No");
else printf("Yes %d\n",ans);
fflush(stdout);
}
return 0;
}