第一屆中興捧月演算法大賽迪傑斯特拉派解決方案

2021-08-02 02:10:12 字數 3879 閱讀 7729

迪傑斯特拉派初賽賽題

最強大腦中的收官蜂巢迷宮**級挑戰,相信大家都嘆為觀止!最強大腦收官戰打響後,收視率節節攀公升,就連蟻后也不時出題難為一下她的子民們。在動物世界中,稱得上活地圖的,除了蜜蜂,螞蟻當仁不讓。在複雜多變的蟻巢中, 螞蟻總是能以最快、最高效的方式遊歷在各個儲藏間(儲存食物)。今天,她看完最新一期節目,又發布了一項新任務:小蟻同學,我需要玉公尺庫的玉公尺,再要配點水果,去幫我找來吧。小蟻正準備出發,蟻后又說:哎呀,回來,我還沒說完呢,還有若干要求如下:

1.小蟻同學,你需要盡可能以最少的花費拿到食物(附件圖中路線上的數值表示每兩個儲物間的花費);

2.小蟻同學,你最多只能經過9個儲藏間拿到食物(包含起止兩個節點,多次通過同一節點按重複次數計算);

3.小蟻同學,你必須經過玉公尺間,水果間(附件圖中標綠色節點);

5.最後,千萬別忘了,還有兩段路是必須經過的,那裡有我準備的神秘禮物等著你呢(附件圖中標綠色路段)。

這下小蟻犯難了,這和它們平時找食物的集體活動規則不一樣嘛,看來這次需要單獨行動了。要怎麼選路呢?小蟻經過一番苦思冥想,稿紙堆了一摞,啊,終於找到了!親愛的同學們,你們能否也設計一種通用的路徑搜尋演算法,來應對各種搜尋限制條件,找到一條最優路徑,順利完成蟻后布置的任務呢?

注:1、蟻巢,有若干個儲藏間,儲藏間之間有諸多路可以到達;

2、節點本身通行無花費;

3、該圖為無向圖,可以正反兩方向通行,兩方向都會計費,並且花費相同;

4、起止節點分別為附件圖中s點和e點。

5、最優路徑:即滿足限制條件的路徑。

附在**下面了,我的解決方案是對整個圖進行乙個限制路徑的dij,用乙個set來判斷特殊點的個數,之後對特殊情況進行判斷一下就行了。這個解法主要的優點是通用,的確犧牲了一下次優解的情況,只有70分,沒拿到區域優勝有點可惜。順便幫助隊友拿到數模校賽一等獎(題目一樣)

#include 

#define inf 0x3f3f3f3f

using

namespace

std;

const

int maxnum = 100;

const

int maxint = 999999;

int dist[maxnum]; //initialize with maxint

int prev[maxnum];

int c[maxnum][maxnum]; //initialize with maxint

int n, line; // 圖的結點數和路徑數

set sp_nodes;

bool sp_edge[maxnum][maxnum];

// n -- n nodes

// v -- the source node

// dist -- the distance from the ith node to the source node

// prev -- the previous node of the ith node

// c -- every two nodes' distance

inline

long

long fac(int n)

return res;

}void dijkstra_modify(int n, int v)

dist[v] = 0;

s[v] = 1;

for(int i=1; iint tmp = maxint;

int u = v;

for(int j=0; jif((!s[j]) && dist[j]// let the special nodes and the current point's edge minimum

// but if there are mutiple of special node ?

}s[u] = 1;

// refresh extend

// no need to change

for(int j=0; jif((!s[j]) && c[u][j]int newdist = dist[u] + c[u][j];

if(newdist < dist[j])}}

}void print(int x,int s)

q.push(s);

while(q.empty()==0)

cout

<<"\n";

}int main()

}for(int i=0; icin>>t1>>t2>>t3;

c[t1][t2] = c[t2][t1] = t3;}//

cin>>st_node>>tm_node;

for(int i=0; i<2; i++)

for(int i=0; i<2; i++)

//edge that unreachable

cin>>t1>>t2;

c[t1][t2] = c[t2][t1] = maxint;

//begin

vector

path,path_p;

vector

sp_nodes_p;

int cnt=0;

int ans=maxint;

int cnt_nodes=0;

for(set

::iterator sit = sp_nodes.begin(); sit!=sp_nodes.end(); sit++)

int times=fac(sp_nodes.size());

for(int i=0; i//generate the permutation

next_permutation(sp_nodes_p.begin(),sp_nodes_p.end());

path_p.clear();

vector

::iterator it = sp_nodes_p.begin();

dijkstra_modify(n,st_node);

cnt += dist[*it];

path.push_back(*it);

//cout<<"st: "memcpy(sp_edge_p,sp_edge,sizeof(sp_edge_p));

bool flag = true;

while(1)

if(sp_edge_p[tmp][*it])

else

}if(!flag)

dijkstra_modify(n,tmp);

cnt += dist[*it];

//refresh the temp

//cout<<"short : "<"<<*it<<" : ";

//print(*it,tmp);

stack

q;int tmp2=*it;

while(tmp2!=tmp)

while(q.empty()==0)

//cout<}

}if(!flag)

int e=sp_nodes_p[sp_nodes_p.size()-1];

dijkstra_modify(n,e);

cnt+=dist[tm_node];

//cout<<"path :";

int judge=st_node;

//cout cnt)

cnt_nodes=path.size();

}cnt=0;

}cout

<<"distance :"

cout

<<"path :"

<"->";

for(int i=0; iif(judge == path[i]) continue;

cout

<"->";

judge=path[i];

}cout

6)

ChinaUnix第一屆「C語言」開發大賽的第三題

3.從標準輸入中讀入 n 1行以換行符結束且長度不超過 2048 的字串,並在輸入結束後輸出其中最長 10行的輸入序號 長度和內容。當有多行長度相等的最長行時,輸出最先輸入的行的資訊。個人寫的 如下 include include include define len sizeof struct l...

ChinaUnix第一屆「C語言」開發大賽的第二題

第二題 給定 n 3 n 50000 個閉區間 ai,bi 1 i n,ai,bi 均為非負整數 將這些區間合併為不相交的閉區間。輸入檔案 的第一行包含乙個整數n,為區間的數目。以下有n行,每行各包括兩個空格分隔的整數ai 和bi,表示乙個區間 ai,bi 0 ai bi 1000000 計算結果寫...

ChinaUnix第一屆「C語言」開發大賽的第一題

給定乙個整數n,生成乙個n n的矩陣,矩陣中元素取值為1至 n2,1在左上角,其餘各數按順時針方向旋轉前進,依次遞增放置。例如,當 n 4時,矩陣中的內 容如下 12 341213145 1116156 10987 個人寫的 如下 include include 矩陣賦值 思想是 就是一圈一圈的賦值...