题目描述
有一个30行30列的矩阵,每个格子是‘o’或者是‘.’。其中前者表示有一枚银币,后者表示没有银币。下面的两个步骤合起来,称为一次操作:
首先,你选择一个方向:上、下、左、右。
然后,把所有的银币往你选择的方向移动一格。如果这个操作会使某些银币越出了矩阵的界,那么越界的银币会自动消失。
你现在的任务是:用最少的操作次数,使得矩阵里剩下的银币数量恰好是K,输出最少的操作次数。如果不可能完成任务,输出-1.
输入格式
第一行,三个整数R、C、K。1 <= R,C <= 30. 1<=K<=900.
接下来是R行C列的矩阵。
输出格式
一个整数。
输入/输出例子1
输入:
3 4 3
.o..
oooo
..o.
输出:
2
输入/输出例子2
输入:
6 6 12
.....o
......
oooooo
oooooo
......
o.....
输出:
3
样例解释
样例一解释:
其中一种最优方案是
向右移动两次
样例二解释:
其中一种最优方案是
向上移动
向下移动
向下移动
具体代码
#include<bits/stdc++.h>
using namespace std;
void construction(int n,int m,int array[][101],int prefix[][101])
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
prefix[i][j]=prefix[i-1][j]+prefix[i][j-1]-prefix[i-1][j-1]+array[i][j];
}
}
}
int regionsum(int n,int m,int xf,int xs,int yf,int ys,int prefix[][101])
{
return prefix[xs][ys]-prefix[xf-1][ys]-prefix[xs][yf-1]+prefix[xf-1][yf-1];
}
int r,c,a[101][101],m[101][101],L=1000000,k,ans;
char t;
int main(){
cin>>r>>c>>k;
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
cin>>t;
if(t=='o')a[i][j]=1;
}
}
construction(r,c,a,m);
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
for(int x=i;x<=r;x++)
{
for(int y=j;y<=c;y++)
{
if((regionsum(r,c,i,x,j,y,m))==k)
{
ans=(i-1)+(j-1)+(r-x)+(c-y);
ans+=min((i-1),(r-x));
ans+=min((j-1),(c-y));
L=min(L,ans);
}
}
}
}
}
if(L==1000000)L=-1;
cout<<L;
return 0;
}
给个免费的赞呗