B监狱 noip 模拟 7.29(区间DP)
作者:互联网
监狱
题目描述 有一座监狱,有N个牢房,N个牢房呈一字排成一排的。也就是说,第i个牢房紧挨着第i+1个(除了末尾那个)。每个牢房里都关押着一名罪犯,总共N名罪犯。
上级要求将某些罪犯释放,给了一份名单,要求每天释放一个人。
位于相邻牢房的罪犯,他们互相之间可以谈话也可以传话,这就使得这里的N名罪犯都可以相互聊天。如果有一个人离开了,那么能和说他上话的人就会很狂躁。如果想让他们安静下来,看守必须给狂躁的人吃一顿火锅。但看守们希望送火锅的次数越少越好。请你计算需要送火锅的次数。
123 输入格式 第一行两个数N和M,M表示要释放名单上的人数;
第二行M个数,表示释放哪些人
12 输出格式 仅一行,表示最少要给多少人次送火锅吃。
1 样例输入 20 3
3 6 14
12 样例输出 35 这道题我真的是想了很久QAQ 开先打了个70 分算法 一直纠结 O(m^3) 算法 网上找了好久 题解也看了 很多 终于悟出了一些小细节 定义 f[i][j] 表示 i 到 j 号 囚犯已经被释放 注意 是被释放的囚犯 所以 对于 每一个小区间的状态都是 于原区间一样 那么i号释放的代价 为 他左右两边 的没有释放资格的囚犯数 所以枚举断点 k K 将 i 到 j 分成 区间 [i,k-1] [k+1,j] 对于每个区间 都已经被算好了 k 就是第一个来更新 [i,j]的 才会 把 [i,j] 分成两个独立的区间 所以代价为 a[j+1]-a[i-1]-2 (这里想了很久,其实想想也是 对于区间 [i,j] 是释放囚犯的集合 他其实包含了没有释放资格的囚犯 a[j+1]-a[i-1]-2 是 i- 1号释放囚犯 和 j+1 号释放囚犯间的 人数) -2? 因为 自己不更新 所以我们有状态转移方程 f[i][j]=min(f[i][j],f[i][k-1]+f[k+1][j]+a[j+1]-a[i-1]-2); 时间复杂度 O(M^3) code:
// #include<stdio.h> #include<bits/stdc++.h> using namespace std; #define maxnn 4002 int f[maxnn][maxnn]; int n,m; int a[101]; int s[maxnn][maxnn]; int sum[maxnn]; int res[maxnn]; int main() { cin>>n>>m; for(int i=1;i<=m;i++) { cin>>a[i]; } sort(a+1,a+1+m); a[m+1]=n+1; for(int i=m;i>=1;i--) for(int j=i;j<=m;j++) { f[i][j]=1e9; for(int k=i;k<=j;k++) f[i][j]=min(f[i][k-1]+f[k+1][j]+a[j+1]-a[i-1]-2,f[i][j]); }cout<<f[1][m]; }
至于为甚么 a[m+1]=n+1;因为 n节点不是一个有释放资格的囚犯
标签:释放,囚犯,7.29,noip,int,牢房,区间,maxnn,DP 来源: https://www.cnblogs.com/OIEREDSION/p/11279740.html