深搜+dijkstra_Poj_1062_昂貴的聘禮

//本來打算練個最短路的 但看到題目有”等級“限制,就改成用深搜做了。 (32Ms)
//因爲把等級這個元素放入DFS函數中進行比放到節點中實現要方便的多
//PS:網上找來了這題 的dijkstra,挺好的,又短又高效,註釋了下(0Ms)

                                                              /*深搜解法*/
#include<iostream>
using namespace std;
#define Max 999999999;
//定義相連表節點結構
struct Edge{
int dest,value;
Edge *link;
};

Edge *edge[100];//定義相連表,以及一個指針

int M,N;//地位等級差距和物品總數

//定義個實際節點
struct Node{
int P,L,X;
int D;//表示最短路
};

Node node[100];//定義實際節點對象

//深搜
void dfs(int max_level,int min_level,int now_i,int lenth_sum)
{
node[now_i].D=lenth_sum;
Edge *l=edge[now_i];
int tmax_level,tmin_level;//存儲下一個節點的最大最小Level
while(l)
{
//判斷當前狀態下可否訪問下一個節點(就是考慮level)
if(max_level - node[l->dest].L <=M && node[l->dest].L - min_level <=M)
{
//下一節點的權限設置好
tmax_level = max_level,tmin_level = min_level;
if(node[l->dest].L > max_level)
tmax_level = node[l->dest].L;
else if(node[l->dest].L < min_level)
tmin_level = node[l->dest].L;
//搜索子節點
       if(node[now_i].D+l->value<node[l->dest].D)//如果該點長度加上下一路徑小於子節點的D
dfs(tmax_level,tmin_level,l->dest,node[now_i].D+l->value);
}
l = l->link;
}
}

int main()
{
int P,L,X;
while(cin>>M>>N)
{
int i,j;
for(i=0;i<N;i++)
edge[i]=NULL;//初始化原始鏈表
Edge *l;
for(i=0;i<N;i++)
{
cin>>P>>L>>X;
node[i].P=P,node[i].L=L,node[i].X=X,node[i].D=Max;//初始化實際節點
//初始化相連鏈表
int dest,value;
for(j=0;j<X;j++)
{
cin>>dest>>value;
l=new Edge;
l->dest=dest-1;
l->value=value;
l->link=edge[i];
edge[i]=l;
}
}
node[0].D=0;
//深搜
dfs(node[0].L,node[0].L,0,0);
//找出最小的並輸出
int value = 999999999;
for(i=0;i<N;i++)
if(node[i].P+node[i].D < value)
value = node[i].P+node[i].D;
printf("%d\n",value);
}
return 0;
}


                                                                 /*dijkstra算法_相連矩陣(0Ms)*/

#include<stdio.h>
#include<string.h>
#define INF 1<<30//2的29次方
//w:,p:價格,d:最短路徑,sta:等級, v:可訪問的點是否已經訪問過,de:可訪問性
int w[101][101],p[101],d[101],sta[101],v[101],de[101];
int main() {
int M,N,i,j,k; scanf("%d %d",&M,&N);
for(i=1;i<=N;i++)
{
for(j=1;j<=N;j++)
w[i][j]=INF;
}
int t1,t2,num,n,price;
//初始化
for(i=1;i<=N;i++)
{
scanf("%d %d %d",&p[i],&sta[i],&num);
for(j=0;j<num;j++)
{
scanf("%d %d",&n,&price); 
w[i][n]=price;//初始化相連矩陣
}
}
int ans=INF;
int bottom=sta[1]-M;//所有可能性的設置等級底限
for(k=bottom;k<=sta[1];k++)//等級底限可變動,因爲低等級的可不取轉而要高等級
{
//初始化最短路徑d
d[1]=0;
for(i=2;i<=N;i++)
d[i]=INF;
t1=k;t2=t1+M;//高等級的上限是sta[1]+M
int s=N;
memset(v,0,sizeof(v));
memset(de,1,sizeof(de));//記錄是否可訪問
//計算出當前權限範圍內可訪問的個數S
for(i=2;i<=N;i++)
{
if(sta[i]<t1||sta[i]>t2)
{
de[i]=0;
s--;
}
}
//dijkstra算法
for(i=1;i<=s;i++){
int x,m=INF;
for(j=1;j<=N;j++)
if(de[j]&&!v[j]&&d[j]<m)
m=d[x=j];//複合句,挺好的
v[x]=1;
for(j=1;j<=N;j++)
if(de[j]&&d[j]>d[x]+w[x][j]) d[j]=d[x]+w[x][j];
}
for(i=1;i<=N;i++)
if(de[i]&&d[i]+p[i]<ans) ans=d[i]+p[i];
}
printf("%d\n",ans);
return 0;
}
出自:http://blog.csdn.net/agralol/article/details/5835771


                                               /*dijkstra_相連表(16Ms)*/

//學了上面的例子,知道等級可以這樣處理 ,於是用相連表做了遍

#include<iostream>
using namespace std;
#define Max_value 999999999;
int M,N;
struct Edge{
int dest,value;
Edge *link;
}*edge[101],*l;//相連鏈表和一個活動指針
struct Node{
int P,L,D,least_D;
bool IsInLevel,IsBeen;
}node[101];//節點


int main()
{
int i,j,num;
while(cin>>M>>N)
{
//初始化節點和鏈表
for(i=1;i<=N;i++)
{
cin>>node[i].P>>node[i].L>>num;
node[i].least_D = Max_value;
edge[i] = NULL;//相連鏈表初始爲空
for(j=0;j<num;j++)
{
l= new Edge;
cin>>l->dest>>l->value;
l->link=edge[i];
edge[i]=l;
}
}
int bottom_level = node[1].L - M;
for(i=bottom_level;i<=node[1].L;i++)//執行dijkstra算法的次數
{
if(i<0) continue;//因爲L非負,可剪枝
int max_level = i+M,min_level=i;
int sum = N;//記錄可進行操作的個數
for(j=1;j<=N;j++)
{
node[j].D = -1;
node[j].IsBeen = false;
if(node[j].L<min_level||node[j].L>max_level)
{
node[j].IsInLevel = false;
sum--;
}
else node[j].IsInLevel = true;
}
//開始執行dijkstra算法
node[1].D=node[1].least_D=0;
int k;
for(k=1;k<=sum;k++)//將頂點最短路標記爲到達,執行sum次
{
int min_i=1,min_value;
min_value = Max_value;
for(j=1;j<=N;j++)
{
if(node[j].IsInLevel && !node[j].IsBeen && node[j].D>=0 && node[j].D<min_value)
min_value=node[min_i=j].D;
}
if(min_i==1 && node[1].IsBeen) break;//這個剪枝可以從64Ms到16Ms,說明有些點是不可達到的
l=edge[min_i];
while(l)
{
int dest = l->dest;
if(node[dest].IsInLevel && !node[dest].IsBeen && (node[dest].D<0|| node[dest].D>node[min_i].D + l->value))
node[dest].D=node[min_i].D + l->value;
l = l->link;
}
if(node[min_i].D<node[min_i].least_D) node[min_i].least_D=node[min_i].D;
node[min_i].IsBeen = true;
}
}
//輸出
int min_cost = Max_value;
for(i=1;i<=N;i++)
if(node[i].least_D!=999999999 && min_cost>node[i].least_D + node[i].P)
min_cost = node[i].least_D + node[i].P;
printf("%d\n",min_cost);
}
return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章