我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html
题目传送门:https://www.luogu.org/problemnew/show/P2003
我们先来灵性地怼一波出题人:
首先他在题目描述的第一段的最后一句话如是说道:“任意一平板的两端必需有支柱或者它在另一块平板上。”
意思就是如果某块板子搭在另一块板子上,那么就可以省去一个脚的柱子。
然后他在输入格式中如是说:“输入保证任意两块平板间没有重叠部分。”
然后我没仔细看题目描述,就以为不可能有板子重叠……所以我直接按高度排序在低于它的板子里找下面一块了……
然后狂\(Wa\)不止。不过机智如我,想到自己经常漏读题面然后就去反复读了几遍题面。
然后机房传出一声惨叫:
傻逼出题人傻逼出题人傻逼出题人
我\(TM\)题面看错了!
所以正确做法是\(n^2\)暴力去找对于每一块板子高度小于等于当前板子并且可以支撑当前板子的某半部分的最高板子。把柱子高度累加起来就可以了。
时间复杂度:\(O(n^2)\)
空间复杂度:\(O(n)\)
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
int n,ans;//n块板子,ans累计柱子高度
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}//快读
struct lines {
int x1,x2,y;
bool operator<(const lines &a)const {
return y>a.y;
}
}q[105];//存板子
int main() {
n=read();
for(int i=1;i<=n;i++)
q[i].y=read(),q[i].x1=read(),q[i].x2=read();
q[n+1].y=0,q[n+1].x1=0,q[++n].x2=10001;//加一块高度为0的极长的板子方便统计柱子到地上的柱子高度
sort(q+1,q+n+1);//按高度排序
for(int i=1;i<n;i++) {
for(int j=1;j<=n;j++)
if(q[j].y<=q[i].y&&i!=j)
if(q[j].x1<=q[i].x1&&q[i].x1<q[j].x2) {
ans+=q[i].y-q[j].y;break;
}//找左边的柱子落脚点,break是因为排过序后后面的板子显然不优
for(int j=1;j<=n;j++)
if(q[j].y<=q[i].y&&i!=j)
if(q[j].x1<q[i].x2&&q[i].x2<=q[j].x2) {
ans+=q[i].y-q[j].y;break;
}//找右边柱子落脚点
}printf("%d\n",ans);
return 0;
}