I. Postal Delivery(2016 ICPC Mid-Central USA Region题解)

INPUT
3 100 
-10 50 
10 175
25 20
OUTPUT
90

INPUT
5 3
-1002 800 
-1001 800
-1000 800 
-999 800 
-998 800
OUTPUT
2668000

题意:有n个需要送信的点,每次可以送m封信,接下来n组,x(地点坐标),y(该地点需要送的信的数量),需要回到原点,问最短走的路程是多少。

思路:按照地点先排好序,计算出坐标轴右侧的,原则是先送最远的,顺带往坐标轴中间凑,能够顺带送的每次都更新。具体看代码。

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int mod=1e9+10;
const int M= 1e4 + 10;
struct A
{
    int p,q;
}a[M];
bool cmp(A pp,A qq)
{
    if(pp.p == qq.p)
        return pp.q<qq.q;
    return pp.p<qq.p;
}
int main()
{
    int n,m,i,j,sum=0;
    cin>>n>>m;
    for(i=0;i<n;i++)
    {
        cin>>a[i].p>>a[i].q;
        if(a[i].p >= 0)
            sum++;
    }
    sort(a,a+n,cmp);
    ll ans=0,x,y;
    for(i=n-1;i>= n-sum;i--)//计算坐标轴右侧的
    {
        x=a[i].q/m;
        y=a[i].q%m;
        ans+=x*a[i].p*2;
        if(y!=0)
        {
            ans+=a[i].p*2;//多出来的也按照路程长的来计算
            y=m-y;
            for(j=i-1;j>=n-sum;j--)//更新前面可以顺便送的
            {
                if(a[j].q>=y)
                {
                    a[j].q-=y;
                    y=0;
                    break;
                }
                else//继续向前更新
                {
                    y-=a[j].q;
                    a[j].q=0;
                }
            }
        }
    }
    for(i=0;i<= n-sum-1;i++)//计算坐标轴左侧的
    {
        x=a[i].q/m;
        y=a[i].q%m;
        ans+=x*(-a[i].p)*2;
        if(y!=0)
        {
            ans+=(-a[i].p)*2;
            y=m-y;
            for(j=i+1;j<=n-sum-1;j++)
            {
                if(a[j].q>=y)
                {
                    a[j].q-=y;
                    y=0;
                    break;
                }
                else
                {
                    y-=a[j].q;
                    a[j].q=0;
                }
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

可以做做这个类似的题目 Postman

postman 题解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值