题意:回合制游戏......齐齐先手,每次攻击完司机,然后司机打齐齐攻击司机的那一个物品,但是每次会有连锁反应.......真就是我打别人,然后极限一换一
题解:搜索+贪心
先求对于司机多少次连锁反应可以团灭
再求对于齐齐多少次连锁反应可以团灭
然后比较两个的次数
如果齐齐的次数<司机的次数,输出-1
否则,求齐齐用来极限一换一的连锁的那几个大炮,产生连锁反应,所损失的最小的大炮数,然后总数再减去损失数就是答案
求连锁反应的可以用搜索,对于每次的求的时候要标记,防止重复,就是求每一次的连锁反应可以影响多少个大炮
然后把求的连锁反应所影响的大炮的个数从小到大排序,取前司机团灭数个求和
时间复杂度: 实际要高于的,但是每次搜索有标记所以还是比较趋近的
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll MOD=1e9+7;
int num,w,numq,nump,qq[10000],pp[10000];
char q[10][110],p[10][110];
bool visq[10][110],visp[10][110];
void dfsp(int x,int y)
{
if(visp[x][y])
return;
num++;
visp[x][y]=1;
for(int i=-1;i<=1;i++)
{
for(int j=-1;j<=1;j++)
{
if(i==j&&i==0)
continue;
int nx=x+i,ny=y+j;
if(nx<=0||ny<=0||nx>4||ny>w)
continue;
if(p[nx][ny]=='*')
dfsp(nx,ny);
}
}
}
void dfsq(int x,int y)
{
if(visq[x][y])
return;
num++;
visq[x][y]=1;
for(int i=-1;i<=1;i++)
{
for(int j=-1;j<=1;j++)
{
if(i==j&&i==0)
continue;
int nx=x+i,ny=y+j;
if(nx<=0||ny<=0||nx>4||ny>w)
continue;
if(q[nx][ny]=='*')
dfsq(nx,ny);
}
}
}
int main()
{
cin>>w;
for(int i=1;i<=4;i++)
for(int j=1;j<=w;j++)
cin>>p[i][j];
for(int i=1;i<=4;i++)
for(int j=1;j<=w;j++)
cin>>q[i][j];
for(int i=1;i<=4;i++)
{
for(int j=1;j<=w;j++)
{
if(p[i][j]=='*'&&!visp[i][j])
{
num=0;
dfsp(i,j);
pp[nump++]=num;
}
}
}
for(int i=1;i<=4;i++)
{
for(int j=1;j<=w;j++)
{
if(q[i][j]=='*'&&!visq[i][j])
{
num=0;
dfsq(i,j);
qq[numq++]=num;
}
}
}
if(nump>numq)
printf("-1\n");
else
{
int total=0;
sort(qq,qq+numq);
for(int i=0;i<numq;i++)
total+=qq[i];
for(int i=0;i<nump-1;i++)
total-=qq[i];
printf("%d\n",total);
}
return 0;
}
京公网安备 11010502036488号