POJ 1116 Library

终于TMD过了...细节真多,没有考虑全,看了人家的AC代码才修改成功.....唉...两次枚举+一个评估函数...评估函数除了分类讨论,还是TMD分类讨论....

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef struct Shelf{
int y;
int x;
int len;
int x1,x2;
}Shelf;
typedef struct Ans
{
int x,y;
};
Shelf s[101];
int Xn,Yn,Xt,Yt,n;
bool cmp(Shelf a,Shelf b)
{
    return a.y>b.y;
}
Ans Judge(int c,int x)//第c个木板 离壁龛左侧有x距离  
{
  Ans ans={0,0};bool flag;
  int left=x,right=x+Xt;//书在x上的左右端点
  int pos_1,pos_2,t;
  for(int i=0;i<c;i++)
  {  
      pos_1=s[i].x+s[i].x1;
      pos_2=s[i].x+s[i].x2;
      if(s[i].x>=right||s[i].x+s[i].len<=left||s[i].y>=s[c].y+Yt) continue;
      if(pos_2<=left) 
      {
          if(left-pos_1<pos_1)  t=2*(left-pos_1);else t=x;
          if(t<s[i].len)  ans.y+=s[i].len-t;
      }     
      else if(pos_1>=right)
      {
          if(pos_2-right<Xn-pos_2) t=2*(pos_2-right);else t=Xn-right;
          if(t<s[i].len)  ans.y+=s[i].len-t;
      }
      //以上不移动木栓  
      else if(pos_1<=left&&pos_2>left&&pos_2<right)
      {
          if(s[i].len>left) ans.y+=s[i].len-left;
          ans.x++;
          if(left==0) ans.x++;
      }
      else if(pos_1>left&&pos_1<right&&pos_2>=right)
      {
          if(s[i].len>Xn-right) ans.y+=s[i].len+right-Xn;
          ans.x++;
          if(right==Xn) ans.x++;
      }
      else if(pos_1<=left&&pos_2>=right)
      {
          int t=min(s[i].len-Xn+right,s[i].len-left);
          ans.y+=t<0?0:t;
          ans.x++;
          if(t==s[i].len) ans.x++;
      }
      //以上移动一个木栓
      else 
      {ans.x+=2;
       ans.y+=s[i].len;
      }
  }
  return ans;
}
Ans EnumPosition(int c)//第2次枚举
{
    Ans ans={1<<21,1<<21},t;
    if(s[c].len<Xt||Yn-Yt<s[c].y) return ans;
    for(int i=0;i+Xt<=Xn;i++)
    {  
        t=Judge(c,i);
        if(i+s[c].len<s[c].x1) continue;
        if(s[c].x2+s[c].len<i+Xt) break;
        if(2*(s[c].x1+s[c].x-i)>s[c].len||2*(i+Xt-s[c].x2-s[c].x)>s[c].len
            ||s[c].x2+s[c].x-i>s[c].len||i+Xt-s[c].x1-s[c].x1>s[c].len) t.x++;
        if(t.x<ans.x) {ans=t;continue;}
        if(t.x==ans.x&&t.y<ans.y) ans=t;
   }
return ans;
}
int main()
{  
    Ans ans,t;
   while(~ scanf("%d%d%d%d%d",&Xn,&Yn,&Xt,&Yt,&n))
   {  
    ans.x=ans.y=1<<20;
    for(int i=0;i<n;i++)
        scanf("%d%d%d%d%d",&s[i].y,&s[i].x,&s[i].len,&s[i].x1,&s[i].x2);
    sort(s,s+n,cmp);
    for(int i=0;i<n;i++)//第一次枚举
    {
        t=EnumPosition(i);
        if(t.x<ans.x) {ans=t;continue;}
        if(t.x==ans.x&&t.y<ans.y) ans=t;
    }
    printf("%d %d\n",ans.x,ans.y);
   }
}   



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值