P4766 [CERC2014]Outer space invaders 题解
小小讲一讲吧,写篇题解。
条件
-
非常小,大概 能过。
-
有编号,时间,距离三个要素。
-
时间很大,不可能直接作为数组的两维。
思路
出于对上述条件的考虑,一位大佬思考过后决定使用区间dp,并教会了我。
-
用离散化后的时间作为数组的两维。
-
而后每次枚举时间的时候,找到这在当前时间区间中距离最大的外星人。由于这个外星人必须被杀,且杀完它之后其他外星人都被杀了,所以我们直接考虑它就可以了。
状态转移方程
为当前区间距离最大的外星人的编号。
code
#include<bits/stdc++.h>
using namespace std;
const int N=750,Inf=11000*300;
template<class T> T read(T &x){
char c=getchar();bool f=0;x=0;
while(!isdigit(c)) f|=c=='-',c=getchar();
while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
return f?-x:x;
}
int T,n;
int dp[N][N],tim[N],id[11000];//tim为离散数组,注意数组的大小
struct node{
int l,r,d;
}a[N];
int main(){
read(T);
while(T--){
read(n);
int cnt=0;
memset(dp,0,sizeof(dp));//初始化重点
for(int i=1;i<=n;i++) read(a[i].l),read(a[i].r),read(a[i].d),tim[++cnt]=a[i].l,tim[++cnt]=a[i].r;
sort(tim+1,tim+cnt+1);
for(int i=1;i<=cnt;i++) id[tim[i]]=i;
for(int i=1;i<=n;i++) a[i].l=id[a[i].l],a[i].r=id[a[i].r];//离散化
for(int len=1;len<cnt;len++){
for(int i=1;i+len<=cnt;i++){
int j=i+len,now=0;
dp[i][j]=Inf;//初始化
for(int k=1;k<=n;k++){//寻找max
if(a[k].l>=i&&a[k].r<=j)
if(!now||a[k].d>a[now].d) now=k;
}
if(!now) {dp[i][j]=0;continue;}//dp[i][j]=0没有敌人
for(int k=a[now].l;k<=a[now].r;k++) dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+a[now].d);
}
}
printf("%d\n",dp[1][cnt]);
}
}
/*
1
3
1 4 4
4 7 5
3 4 7
*/
/*
7
*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现