UVALive 6834

来源:互联网 发布:短域名批量生成 编辑:程序博客网 时间:2024/03/29 14:40

购物

题目描述:

给出N个点~1000,就是1到N。然后给出m条边,每个是di到ci,意思是只有到达过di之后到达ci才算到达过ci。求:从1出发,将1到N个点全部搞完然后到N点的总距离。

题解:

很好的一道题。首先发现区间不连续,不能够用dp。然后研究性质,发现:如果di》ci,就增加一个区间ci到di,表明要额外走双份,这样都处理后,发现如果di《ci是不用弄的,因为所有与di和ci有关的都搞过了。之后就是拿着已经增添的区间来搞出要多走两次的部分,其实就是区间覆盖的地方只算一次。
区间覆盖:按左端点排序,然后记录当前左端点不间断到达的最远右处。

重点:

发现有边的需要重复走,并且节省重复走的可以将覆盖的只走一遍,由此启发出解法:将需要重走的搞出区间,然后变成了区间覆盖。

代码:

//晨豪的代码#include <cstdio>#include <cstring>#include <vector>#include <queue>#include <algorithm>using namespace std;const int N = 1010;int n,m;int tot;int cnt;struct P{    int l,r;}a[N],b[N];void init(){    tot = cnt = 0;    for (int i = 1; i <= m; i++)    {        int aa,bb;        scanf("%d %d",&aa,&bb);        if (bb < aa) continue;        a[++tot].l = aa;//搞出需要的区间        a[tot].r = bb;    }}int com(P x,P y)//左端点排序{    if (x.l == y.l) return x.r < y.r;    return x.l < y.l;}void solve(){    init();    sort(a+1,a+tot+1,com);    int ans = n+1;    int l = a[1].l,r = a[1].r;    for (int i = 2;i <= tot;i++)//区间覆盖    {        if (r < a[i].l)        {            b[++cnt].l = l;            b[cnt].r = r;            l = a[i].l;            r = a[i].r;        }        else            r = max(r,a[i].r);        if (i == tot)        {            b[++cnt].l = l;            b[cnt].r = r;        }    }    for (int i = 1;i <= cnt;i++)        ans += 2*(b[i].r - b[i].l);    printf("%d\n",ans);}int main(){  //  freopen("in.txt","r",stdin);    while (~scanf("%d %d",&n,&m))    {        solve();    }}
0 0
原创粉丝点击