Sample Input
2 1
#.
.#
4 4
…#
…#.
.#…
#…
-1 -1
Sample Output
2
1
#include
#include
#include
using namespace std;
const int maxn=10;
int n,k,cnt,ans;
char put[maxn][maxn];
int use[maxn];//标记某列是否已被用过
void dfs(int x)//递归行,每行最多用一次
{
if(cnt==k) {++ans;return;}//已用k列,代表已成功防止k个棋子
if(x>n) return;
for(int i=1;i<=n;++i)//枚举列,每列最多用一次
{
if(!use[i]&&put[x][i]!='.')//这一列还没用过,且不是空白区域
{
use[i]=1,++cnt;//在第x行用第i列
dfs(x+1);
use[i]=0,--cnt;//还原用第i列前的状态
}
//继续循环可选择在第x行用第i+1列等,第i列可能以后再用
}
dfs(x+1);//不用这行,直接下一行
}
int main()
{
while(~scanf("%d %d",&n,&k),n!=-1&&k!=-1)
{
memset(use,0,sizeof(use));
ans=0,cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%s",put[i]+1);
}
dfs(1);
printf("%d\n",ans);
}
return 0;
}
由于【引用】中难以输入一排连续的#,故下述输入输出的样例用代码块粘贴
*Sample Input*
3 4 5
S....
.###.
.##..
###.#
#####
#####
##.##
##...
#####
#####
#.###
####E
1 3 3
S##
#E#
###
0 0 0
*Sample Output*
Escaped in 11 minute(s).
Trapped!
#include
#include
#include
#include
#include
using namespace std;
const int maxn=50;
char put[maxn][maxn][maxn];
int L,R,C,sum,ans,time[maxn][maxn][maxn];
int move[6][3]={{-1,0,0},{1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
struct node{int x,y,z;}start,ed,cur,next;//起点,终点,当前,走向的目标位置
int bfs()
{
queue<node> Q;//为了节省循环pop清空队列Q的时间,索性多组输入时每次重建Q即可
Q.push(start);
while(Q.size())
{
cur=Q.front(),Q.pop();
for(int i=0;i<6;i++)//遍历左右前后上下六个方位
{
next.x=cur.x+move[i][0];
next.y=cur.y+move[i][1];
next.z=cur.z+move[i][2];
if(next.x>=0&&next.x<R&&next.y>=0&&next.y<C&&next.z>=0&&next.z<L&&put[next.z][next.x][next.y]!='#'&&time[next.z][next.x][next.y]==0)
{//行、列、高均未越界 且 往当前遍历到的方向走得通 且 还未走到过这个目标位置(不然来回走就不是最短时间了)
time[next.z][next.x][next.y]=time[cur.z][cur.x][cur.y]+1;//更新走到目标位置耗费的时间
if(next.x==ed.x&&next.y==ed.y&&next.z==ed.z) return time[ed.z][ed.x][ed.y];//走到了终点
Q.push(next);//目标位置入队,接下来从目标位置开始走
}
}
}
return -1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
while(cin>>L>>R>>C&&L+R+C)
{
sum=0;
memset(time,0,sizeof(time));
for(int i=0;i<L;++i)
{
for(int j=0;j<R;++j)
{
for(int k=0;k<C;++k)
{
cin>>put[i][j][k];
if(put[i][j][k]=='S') start.z=i,start.x=j,start.y=k;
else if(put[i][j][k]=='E') ed.z=i,ed.x=j,ed.y=k;
}
}
}
ans=bfs();
if(ans==-1) cout<<"Trapped!"<<endl;
else cout<<"Escaped in "<<ans<<" minute(s)."<<endl;
}
return 0;
}
Sample Input
5 17
Sample Output
4
#include
#include
#include
#include
using namespace std;
const int maxn=1e5+10;
int pos,N,K,ans,sign[maxn];
struct movement
{
int pos;
int step;
}Move,t;
bool ok(int x)
{
if(x<0||x>maxn) return false;
return true;
}
void bfs()
{
queue<movement> q;
memset(sign,0,sizeof(sign));
Move.pos=N;//从N开始走
Move.step=0;//初始化时间为0
q.push(Move);
sign[N]=1;//标记是否走到过这个位置,重复走就不是最快的了
while(!q.empty())
{
Move=q.front();
/*
队列是先进先出的,所以每一次三种情况if合理的入队后
会在各自下一步之前先被取出来
*/
q.pop();
if(Move.pos==K)
{
ans=Move.step;
return;
}
else t.step=Move.step+1;//用t记录走到下一个位置的耗时和位置
t.pos=Move.pos+1;
if(ok(t.pos)&&sign[t.pos]==0)
{
sign[t.pos]=1;
q.push(t);
//t入队后再用front提取move,得到的步数和位置都是更新过了的
}
t.pos=Move.pos-1;
if(ok(t.pos)&&sign[t.pos]==0)
{
sign[t.pos]=1;
q.push(t);
}
t.pos=Move.pos*2;
if(ok(t.pos)&&sign[t.pos]==0)
{
sign[t.pos]=1;
q.push(t);
}
}
}
int main()
{
scanf("%d %d",&N,&K);
ans=0x3F3F3F3F;
bfs();
printf("%d\n",ans);
return 0;
}
Sample Input
4 4
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1
Sample Output
0 0 0 0
1 0 0 1
1 0 0 1
0 0 0 0
#include
#include
#include
#include
using namespace std;
const int inf=0x3f3f3f3f;
int a[20][20],b[20][20],c[20][20];//a存图;b保存当前翻转方案;c保存最优解
int move[5][2]={{-1,0},{1,0},{0,0},{0,-1},{0,1}};//五个翻转走向
int n,m,ans=inf;//翻转类开关问题:翻转的顺序并不影响最终结果
bool getcolor(int x,int y)//翻动x,y周围的瓷砖,得到x,y的颜色
{
int res=a[x][y];
for (int i=0;i<5;++i)
{
int fx=x+move[i][0],fy=y+move[i][1];
if(fx>=1&&fx<=n&&fy>=1&&fy<=m) res+=b[fx][fy];//b[fx][fy]是1就要翻它
}//实际只考虑这个位置之前之上和自己翻转的影响,其他还未遍历到改变,且初始化为0
return res%2;//原0则翻奇次变1;原1则翻奇次变0
}
int solve()
{
int res=0;//从第二行开始检查是否需要翻转,上一行是1就要靠其下对应的这一行位置来翻
for(int i=2;i<=n;++i) {for(int j=1;j<=m;++j) {if(getcolor(i-1,j)) b[i][j]=1;}}
for(int i=1;i<=m;++i) {if(getcolor(n,i)) return inf;}//检查最后一行是否全为0
for(int i=1;i<=n;++i) {for(int j=1;j<=m;j++) res+=b[i][j];}//统计翻转次数
return res;
}
int main()
{
scanf("%d %d",&n,&m);//n行m列
for(int i=1;i<=n;++i) {for(int j=1;j<=m;++j) scanf("%d",&a[i][j]);}
for(int s=0;s<1<<m;++s)//按照字典序枚举第一行所有翻转可能,1翻0不翻
{
memset(b,0,sizeof(b));//初始化都不翻转
for(int i=1;i<=m;++i) b[1][i]=(s>>(m-i))&1;//取出s在二进制表示下的第m-i位,二进制第几位是从右数的
int t=solve();//当前情况翻转次数
if(t<ans) {ans=t;memcpy(c,b,sizeof(b));}//此处的memcpy复制b中sizeof(b)个字节到c
}
if(ans==inf) printf("IMPOSSIBLE\n");
else
{
for(int i=1;i<=n;++i) {for(int j=1;j<=m;++j) printf("%d%c",c[i][j],j==m?'\n':' ');}
}
return 0;
}