深搜
题目描述
齐齐和司机在玩单机游戏《红色警戒IV》,现在他们的游戏地图被划分成一个n*m的方格地图。齐齐的基地在最上方的4行格内,司机的基地在最下方的4行格内。他们只有一种攻击方式:远程大炮,相关属性如下:
1、 大炮可以打到地图的任意一个位置。
2、 双方每次必须动用本方的一门大炮攻击,齐齐先手,双方交替进行攻击。
3、 一方大炮只能攻击另一方大炮,不能攻击本方或强制攻击未获得视野的地区。
4、 被一方大炮击中的另一方大炮会产生以攻击点为中心的3*3的波及区域,波及区域内如果有其他大炮则也会产生3*3的波及区域。
5、 两方的基地相距很远,所以不存在攻打敌方大炮时波及到本方大炮的情况。
齐齐偷偷开了“间谍卫星”,所以他能看到司机的大炮部署,司机则无视野。但如果齐齐做出攻击,司机会立即获取到发动攻击的大炮的视野,并在回合开始时动用大炮(如果存在的话)将其摧毁(摧毁后可能产生的连锁不计入视野)。
现在给出齐齐和司机的大炮部署,问齐齐在选择最优的策略下,在摧毁所有司机的大炮后可以保留最多几门本方大炮。
输入描述:
第1行输入一个整数m,表示地图的宽度。 第2-5行,每行输入一串长度为m的字符串,代表司机的大炮部署。(大炮为"*"号,空地为“.”号) 第6-9行,每行输入一串长度为m的字符串,代表齐齐的大炮部署。(大炮为"*"号,空地为“.”号) 数据保证:0<m≤100
输出描述:
输出一行,一个整数。代表摧毁所有司机的大炮后最多保留几门大炮。如果不能摧毁所有司机的大炮,则输出-1。
示例1
输入
3 ... .*. ..* *.. *.. .** ... *.*
输出
4
示例2
输入
3 *.. ..* ... ... ... ... .*. ...
输出
-1
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e2 + 3;
int fa[8 * maxn];
int dis[8 * maxn];
int dxdy[8][2] = { {1, 1}, {1, 0},
{1, -1}, {0, 1},
{0, -1}, {-1, 1},
{-1, 0}, {-1, -1}
};
string s[8];
int playerB;
int playerA;
int num[maxn];
int sum;
int find(int x)
{
if(fa[x]==x) return x;
else fa[x] = find(fa[x]);
}
void unionn(int x, int y) {
int a = find(x);
int b = find(y);
if (a != b)
{
fa[a] = b;
dis[b] += dis[a];
}
}
int main() {
memset(num, 0, sizeof(num));
int m;
scanf("%dis",&m);
for (int i = 0; i < 8; i++)
{
cin >> s[i];
for (int j = 0; j < m; j++)
{
fa[i * m + j] = i * m + j;
dis[i * m + j] = 1;
}
}
for (int i = 0; i < 8; i++)
for (int j = 0; j < m; j++)
if ('*' == s[i][j])
for (int k = 0; k < 8; k++)
{
int dx = i + dxdy[k][0];
int dy = j + dxdy[k][1];
if ( ( dx && dx <= 3 && i <= 3) || (dx >= 4 && dx <= 7 && i >= 4) )
{
if (dy && dy <= m - 1)
{
if ( s[dx][dy]=='*' )unionn(dx * m + dy, i * m + j);
}//如果是齐齐的地盘
}//如果没出界
}
for (int i = 0; i < 8; i++)
for (int j = 0; j < m; j++)
{
int w=i*m+j;
if ('*' == s[i][j] && fa[m] == m)
{
if (i <= 3) playerB++;
else num[playerA++] = dis[i * m + j];
}
}
if (playerA < playerB)
{
cout << -1 << endl;
return 0;
}
sort(num, num + playerA);
for (int i = playerB - 1; i <= playerA - 1; i++)
sum += num[i];
printf("%d\n",sum);
return 0;
}
八数码
描述
在九宫格里放在1到8共8个数字还有一个是空格,与空格相邻的数字可以移动到空格的位置,问给定的状态最少需要几步能到达目标状态(用0表示空格):
1 2 3
4 5 6
7 8 0
输入
输入一个给定的状态。
输出
输出到达目标状态的最小步数。不能到达时输出-1。
输入样例
1 2 3
4 0 6
7 5 8
输出样例
2
#include<iostream>
#include<map>
#include<queue>
using namespace std;
queue<int>Q;
map<int,int>vis;//标记数组
map<int,int>step;//记录到这种状态的步数
int dir[4][2]={-1,0,0,1,1,0,0,-1};//上,右,下,左
int mat[3][3];
int state;//输入的初始状态
int r,c;
void input()//输入数据并将矩阵转化为一个九位整数
{
int tmp=0;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
{
cin>>mat[i][j];
tmp=tmp*10+mat[i][j];
}
state=tmp;
}
bool can_move(int u,int d)//判断是否可以走
{
for(int i=2;i>=0;i--)//将整数变回矩阵才好判断
{
for(int j=2;j>=0;j--)
{
mat[i][j]=u%10;
u/=10;
if(mat[i][j]==0)
{
r=i;
c=j;
}
}
}
//判断四个方向是否能走
if((d==0&&r==0)||(d==1&&c==2)||(d==2&&r==2)||(d==3&&c==0))
return 0;
return 1;
}
int move_to(int u,int d)//返回从状态u走到的状态
{
int tmp=0;
int nr=r+dir[d][0];
int nc=c+dir[d][1];
mat[r][c]=mat[nr][nc];
mat[nr][nc]=0;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
tmp=tmp*10+mat[i][j];
}
return tmp;
}
int bfs(int s)
{
Q.push(s);
vis[s]=1;
step[s]=0;
while(Q.size())
{
int u,v;
u=Q.front();
Q.pop();
if(u==123456780)
return step[u];
for(int i=0;i<4;i++)
{
if(can_move(u,i))
{
v=move_to(u,i);
if(!vis[v])
{
vis[v]=1;
step[v]=step[u]+1;
Q.push(v);
}
}
}
}
return -1;
}
int main()
{
input();
int ans=bfs(state);
cout<<ans<<endl;
return 0;
}