hdu 5361 In Touch 题目特点+优先队列的dijikstra 2015 Multi-University Training Contest 6

来源:互联网 发布:淘宝联盟推广位名称 编辑:程序博客网 时间:2024/04/30 23:20

In Touch

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1208    Accepted Submission(s): 324


Problem Description
There are n soda living in a straight line. soda are numbered by 1,2,,n from left to right. The distance between two adjacent soda is 1 meter. Every soda has a teleporter. The teleporter of i-th soda can teleport to the soda whose distance between i-th soda is no less than li and no larger than ri. The cost to use i-th soda's teleporter is ci.

The 1-st soda is their leader and he wants to know the minimum cost needed to reach i-th soda (1in)
 

Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains an integer n (1n2×105), the number of soda. 
The second line contains n integers l1,l2,,ln. The third line contains n integers r1,r2,,rn. The fourth line contains n integers c1,c2,,cn(0lirin,1ci109)
 

Output
For each case, output n integers where i-th integer denotes the minimum cost needed to reach i-th soda. If 1-st soda cannot reach i-the soda, you should just output -1.
 

Sample Input
152 0 0 0 13 1 1 0 51 1 1 1 1
 

Sample Output
0 2 1 1 -1
Hint
If you need a larger stack size, please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
 

Source
2015 Multi-University Training Contest 6
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:  5368 5367 5366 5365 5364 

题目特点+优先队列的dijikstra

点多边多,用点的dijkstra和优先队列的dijkstra(边)似乎不行,关键是抓住题目的特点,每个点相邻的边权值相同,
那么优先队列里自动排序依据 d[ x ]+w[x]小的放前面就行了,那么每次自动会找到要拓展的点(下一个出发的点)。



另外弄两个容器,其中一个容器装没有被访问的点,每次访问一个元素,都将该元素从容器里删除,另一个容器负责优先队列的实现。

set结构体中若有两个元素a和b,如果重载小于时不考虑a+b相等的情形,最后排完很可能会排掉某些元素。



<span style="font-size:18px;">#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<climits>#include<queue>#include<vector>#include<map>#include<sstream>#include<set>#include<stack>#include<utility>//#pragma comment(linker, "/STACK:102400000,102400000")#define PI 3.1415926535897932384626#define eps 1e-10#define sqr(x) ((x)*(x))#define FOR0(i,n)  for(int i=0 ;i<(n) ;i++)#define FOR1(i,n)  for(int i=1 ;i<=(n) ;i++)#define FORD(i,n)  for(int i=(n) ;i>=0 ;i--)#define  lson   num<<1,le,mid#define rson    num<<1|1,mid+1,ri#define MID   int mid=(le+ri)>>1#define zero(x)((x>0? x:-x)<1e-15)using namespace std;//const int INF =0x3f3f3f3f;const int maxn=2*100000+10    ;//const int maxm=    ;//const int INF=    ;typedef long long ll;const ll inf =1000000000000000;//1e15;//ifstream fin("input.txt");//ofstream fout("output.txt");//fin.close();//fout.close();//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);int le[maxn],ri[maxn];ll c[maxn];ll d[maxn];int n;struct Node{int id;ll w;   bool operator<( const Node &x )const   {        if( w+c[id]!=x.w+c[x.id])  //如果不考虑相等的情况,可能会排掉某些元素。      return   w+c[id]<x.w+c[x.id];      return id<x.id;   }   Node(){}   Node(int i,ll w_):id(i),w(w_){}}   ; set<Node> sq; set<int>  se;void dijkstra(){    se.clear();sq.clear();    for(int i=1;i<=n;i++)        d[i]=inf;    d[1]=0;    sq.insert( Node( 1,d[1]   )    );    for(int i=2;i<=n;i++)    {        se.insert(i);    }    set<int >::iterator it;    set<int >::iterator it2;      while(!sq.empty())         {        Node x=*sq.begin();        sq.erase(sq.begin());        it=se.lower_bound(  x.id-ri[x.id]);        while(it!=se.end()&&  *it<= x.id-le[x.id])//用容器存放未访问的点的优点在于节省时间,每次不用从头遍历,这是基于题目每两个相邻点之间距离是1的特点才采取的。        {            if( d[*it]>d[x.id]+c[x.id])                d[*it]=d[x.id]+c[x.id];            sq.insert( Node( *it,d[*it]   ) );            it2=it++;            se.erase(it2);        }        it=se.lower_bound(  x.id+le[x.id]);        while(it!=se.end()&&*it<=x.id+ri[x.id])        {             if( d[*it]>d[x.id]+c[x.id])                d[*it]=d[x.id]+c[x.id];            sq.insert( Node(*it,d[*it]) );            it2=it++;            se.erase(it2);        }    }//这个算法真正优点在于每次拓展某个点找到的都是最优点(因为正是根据这个来排的,),<span style="color:#ff0000;">所以每个点的d[]只用更新一次。</span>一般的优先队列dijkstra因为每个点出发的边权值不同,所以必须有一步把正在拓展的点的边都遍历一遍,进而贪心求解。}void print(){    putchar('0');    for(int i=2;i<=n;i++)    {        if(d[i]!=inf)            printf(" %lld",d[i]);        else printf(" -1");    }    putchar('\n');}int main(){   int T;scanf("%d",&T);   while(T--)   {       scanf("%d",&n);       FOR1(i,n) scanf("%d",&le[i]);       FOR1(i,n) scanf("%d",&ri[i]);       FOR1(i,n) scanf("%lld",&c[i]);       dijkstra();       print();   }    return 0;}</span>


 
0 0
原创粉丝点击