【题解】Luogu P9287 [ROI 2018] Viruses
题意分析
这个题面比较抽象。
简单来说就是有 \(n\) 个病毒和 \(n\) 个细胞,病毒 \(i\) 开始都在细胞 \(j\) 里面。每个细胞都有针对每个病毒的易感染程度,病毒可以攻击其他细胞,如果目标细胞所存在病毒的对于目标细胞的易感程度小于攻击病毒对于目标细胞的易感染程度,那么目标细胞就会被攻击病毒感染。让你求有多少能在攻击中可能活下来的病毒和一定活下来的病毒。
思路详解
乍一看没有思路,其实这题就是一个模拟。
Problem 1:稳定的病毒
这个问题很简单,只要病毒 \(i\) 初始所在的老家细胞 \(i\) 所对应病毒 \(i\) 的易感程度最高,那么这个病毒就永远不可能会被移除。
Problem 2:可行的病毒
这个问题就比较棘手了,需要模拟。
我们让每个 \(i\) 病毒攻击 \(j\) 细胞,枚举 \(j\) 细胞中可能存在的病毒 \(k\),如果 \(i\) 病毒的易感程度大于存在的 \(k\) 病毒那么就可将其感染。如果病毒 \(i\) 能通过感染 \(k\) 的方式感染本不可以感染的细胞 \(j\),那么其就是可行的病毒。
时间复杂度 \(O(n^3)\),因为 \(n\) 不大于 \(500\),所以可以通过。
通过代码
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=510;
int n,p,cnt;
int v[maxn][maxn],f[maxn][maxn],t[maxn];
int ans[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&v[i][j]);
f[i][v[i][j]]=j;
}
}
scanf("%d",&p);
if(p==1){
for(int i=1;i<=n;i++){
if(v[i][1]==i) ans[++cnt]=i;
}
}else{
for(int i=1;i<=n;i++){
t[i]=n;
for(int j=1;j<=n;j++){
int maxx=0;
for(int k=1;k<=n;k++){
if(f[j][k]<=f[j][j]) maxx=max(f[i][k],maxx);
}
t[i]=min(maxx,t[i]);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(f[j][i]<=f[j][j]&&t[j]>=f[j][i]){
ans[++cnt]=i;
break;
}
}
}
}
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++){
printf("%d ",ans[i]);
}
return 0;
}

浙公网安备 33010602011771号