D . Knight Moves
题目大意:在一个棋盘上给出起点和终点,棋子以走‘日’的方式以最短的路径前往终点。
题目分析:用广度优先搜索,将输入的字符串转化为坐标,然后按照象棋中马的走法前往终点。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mp[26][26],vis[26][26];
ll ty[8] = {-1, 1, -2, 2, -2, 2, -1, 1};
ll tx[8] = {-2, -2, -1, -1, 1, 1, 2, 2};
char a[3],b[3];
ll sx,sy,ex,ey,n,m,flag,minstep;
struct node
{
ll x,y,step;
};
void bfs()
{
queue<node> que;
node q,p;
q.x=sx,q.y=sy,q.step=0;
que.push(q);
while(!que.empty())
{
q=que.front();
if(q.x==ex&&q.y==ey)
{
printf("To get from %s to %s takes %d knight moves.\n",a,b,q.step);
return ;
}
que.pop();
for(int i=0;i<8;i++)
{
p=q;
p.x+=tx[i];p.y+=ty[i];
if(p.x>=1&&p.x<=8&&p.y>=1&&p.y<=8)
if(!vis[p.x][p.y])
{
p.step=p.step+1;
vis[p.x][p.y]=1;
que.push(p);
}
}
}
}
int main()
{
while(scanf("%s%s",&a,&b)!=EOF)
{
memset(vis,0,sizeof(vis));
minstep=1000000;
sx=a[0]-'a'+1;sy=a[1]-'0';
ex=b[0]-'a'+1;ey=b[1]-'0';
vis[sx][sy]=1;
bfs();
}
return 0;
}
E.Patrol Robot
题目大意:一个机器人在m*n的范围内移动,且每一步只能移动一格,移动方向只能有上下左右四个方向,其中会有单元格有障碍物,不能连续穿过超过k个障碍物,求起点到终点的最短路径。
题目分析:一般想到使用bfs,但是多出了障碍物,需要判断穿过或是绕弯,其中遇到四周都为障碍物和穿过次数超过k时无解,输出-1.仅使用bfs无法解决障碍物的问题。队列中存放的结构体中有当前位置的坐标,x,y,还有已经走过的步数member,以及连续走过的障碍方格的个数count. 对于下标不满足条件以及vis标记走过的方格,和连续走过方格的个数超过k的位置,都不放入队列,反之放入队列,继续bfs,直至第一次到达右下角为止。因为每一个从平行的bfs状态下走到同一障碍方格时,可能之前连续走过的障碍方格的个数不同。
所以,在同一位置,会有0~k不同的方格个数的选择,选用二维vis标记数组标记,情况考虑不全的同时还会超时,使用三维vis 标记数组标记,多出的一维用来记录该方格之前连续走过的障碍方格的个数。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
struct pc{
int x,y,member,countt;
};
ll ter[4][2]={1,0,0,1,-1,0,0,-1};
ll maze[110][110],vis[110][110][25];
ll n,m,k;
ll bfs()
{
ll i,xx,yy;
queue<pc> q;
memset(vis,0,sizeof(vis));
pc now,no;
now.x=0; now.y=0;
now.member=1; now.countt=0;
q.push(now);
vis[0][0][0]=1;
while(!q.empty()){
no=q.front();
q.pop();
if(no.x==n-1&&no.y==m-1)
return no.member-1;
for(i=0;i<4;i++){
now.x=no.x+ter[i][0];
now.y=no.y+ter[i][1];
if(now.x>=0 && now.x<n &&now.y>=0 &&now.y<m){
if(maze[now.x][now.y]==1)
now.countt=no.countt+1;
else
now.countt=0;
if(now.countt<=k&&vis[now.x][now.y][now.countt]==0)
{ now.member=no.member+1;
q.push(now);
}
vis[now.x][now.y][now.countt]=1;
}
}
}
return -1;
}
int main()
{
ll f,i,j;
cin>>f;
while(f--){
cin>>n>>m>>k;
for(i=0;i<n;i++){
for(j=0;j<m;j++){
cin>>maze[i][j];
}
}
cout<<bfs()<<endl;
}
return 0;
}
F.Equilibrium Mobile
题目大意:输入字符串,为天平上磅秤的位置和重量,可以任意修改磅秤的重量,要使天平平衡最少需要修改几个磅秤
题目分析:天平结构为二叉树,在知道磅秤的重量w和深度下可以求出这个数的总重量=w*pow(2,depth),因为在某个深度下的完全二叉树节点个数=pow(2,edpth)。因为要使天平平衡那么这层深度的节点的重量全部等于w,再乘上个数就是这棵树的总重量。然后用位运算表示就是:总重量=w<<depth。然后求出每个节点平衡的总重量,那么必然会有一些相等的情况,我们把这写总重量相同的数量计数,也就是说可以得到某个总重量,不需要改变值的数量是w[i],这里用map记录 map[n][w]:表示总重量为w不需要改变n个数,然后我们找到最大多需要改变的数量,用总节点数-最多不需要改变的数量=最少需要改变的数量。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mm=1e6+5;
ll sum=0;
char str[mm];
map<ll,ll>mp;
void dfs(int s,ll t,ll dep){
if(str[s]=='['){
int p=0;
for(ll i=s+1;i<=t;i++){
if(str[i]=='[')p++;
if(str[i]==']')p--;
if(p==0&&str[i]==','){
dfs(s+1,i-1,dep+1);
dfs(i+1,t-1,dep+1);
}
}
}
else{
ll w=0;
for(ll i=s;i<=t;i++){
w=w*10+(str[i]-48);
}
++mp[w<<dep];++sum;
}
}
int main(){
ll t;
cin>>t;
while(t--){
mp.clear();
cin>>str;
sum=0;
dfs(0,strlen(str)-1,0);
ll maxn=0;
for(map<ll,ll>::iterator it=mp.begin();it!=mp.end();it++){
maxn=max(maxn,it->second);
}
cout<<sum-maxn<<endl;
}
}