迪杰斯特拉派初赛赛题
最强大脑中的收官蜂巢迷宫变态级挑战,相信大家都叹为观止!最强大脑收官战打响后,收视率节节攀升,就连蚁后也不时出题难为一下她的子民们。在动物世界中,称得上活地图的,除了蜜蜂,蚂蚁当仁不让。在复杂多变的蚁巢中, 蚂蚁总是能以最快、最高效的方式游历在各个储藏间(存储食物)。今天,她看完最新一期节目,又发布了一项新任务:小蚁同学,我需要玉米库的玉米,再要配点水果,去帮我找来吧。小蚁正准备出发,蚁后又说:哎呀,回来,我还没说完呢,还有若干要求如下:
1.小蚁同学,你需要尽可能以最少的花费拿到食物(附件图中路线上的数值表示每两个储物间的花费);
2.小蚁同学,你最多只能经过9个储藏间拿到食物(包含起止两个节点,多次通过同一节点按重复次数计算);
3.小蚁同学,你必须经过玉米间,水果间(附件图中标绿色节点);
4.别忘了,食蚁兽也在路上活动呢,一旦与食蚁兽相遇,性命危矣!不过小蚁微信群公告已经公布了敌人信息(附件图中标红色路段);
5.最后,千万别忘了,还有两段路是必须经过的,那里有我准备的神秘礼物等着你呢(附件图中标绿色路段)。
这下小蚁犯难了,这和它们平时找食物的集体活动规则不一样嘛,看来这次需要单独行动了。要怎么选路呢?小蚁经过一番苦思冥想,稿纸堆了一摞,啊,终于找到了!亲爱的同学们,你们能否也设计一种通用的路径搜索算法,来应对各种搜索限制条件,找到一条最优路径,顺利完成蚁后布置的任务呢?
注:
1、蚁巢,有若干个储藏间,储藏间之间有诸多路可以到达;
2、节点本身通行无花费;
3、该图为无向图,可以正反两方向通行,两方向都会计费,并且花费相同;
4、起止节点分别为附件图中S点和E点。
5、最优路径:即满足限制条件的路径。
图片附在代码下面了,我的解决方案是对整个图进行一个限制路径的dij,用一个set来判断特殊点的个数,之后对特殊情况进行判断一下就行了。这个解法主要的优点是通用,的确牺牲了一下次优解的情况,只有70分,没拿到区域优胜有点可惜。顺便帮助队友拿到数模校赛一等奖(题目一样)
#include <bits/stdc++.h>
#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<int> 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)
{
int res=1;
while(n!=0)
{
res*=n;
n--;
}
return res;
}
void Dijkstra_modify(int n, int v)
{
bool s[maxnum];
for(int i=0; i<n; i++)
{
dist[i] = maxint;
}
for(int i=0; i<n; ++i)
{
dist[i] = c[v][i];
s[i] = 0;
if(dist[i] == maxint)
prev[i] = 0;
else
prev[i] = v;
}
dist[v] = 0;
s[v] = 1;
for(int i=1; i<n; ++i)
{
int tmp = maxint;
int u = v;
for(int j=0; j<n; ++j)
{
if((!s[j]) && dist[j]<tmp)
{
u = j;
tmp = 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; j<n; ++j)
if((!s[j]) && c[u][j]<maxint)
{
int newdist = dist[u] + c[u][j];
if(newdist < dist[j])
{
dist[j] = newdist;
prev[j] = u;
}
}
}
}
void print(int x,int s)
{
stack<int>q;
int flag(s);
while(x!=s)
{
q.push(x);
x=prev[x];
}
q.push(s);
while(q.empty()==0)
{
cout<<q.top()<<"->";
q.pop();
}
cout<<"\n";
}
int main()
{
freopen("graph_in.txt","r",stdin);
freopen("graph_out.txt","w",stdout);
int t1= 0,t2=0,t3=0;
int st_node,tm_node;
cin>>n>>line;
for(int i=0; i<=n; i++)
{
dist[i]=maxint;
for(int j=0; j<=n; j++)
{
c[i][j]=maxint;
}
}
for(int i=0; i<line; i++)
{
cin>>t1>>t2>>t3;
c[t1][t2] = c[t2][t1] = t3;
}
//
cin>>st_node>>tm_node;
for(int i=0; i<2; i++)
{
cin>>t1;
sp_nodes.insert(t1);
}
for(int i=0; i<2; i++)
{
cin>>t1>>t2;
sp_nodes.insert(t1);
sp_nodes.insert(t2);
sp_edge[t1][t2] = sp_edge[t2][t1] = true;
}
//edge that unreachable
cin>>t1>>t2;
c[t1][t2] = c[t2][t1] = maxint;
//begin
vector<int> path,path_p;
vector<int> sp_nodes_p;
int cnt=0;
int ans=maxint;
int cnt_nodes=0;
for(set<int>::iterator sit = sp_nodes.begin(); sit!=sp_nodes.end(); sit++)
{
sp_nodes_p.push_back(*sit);
}
int times=fac(sp_nodes.size());
for(int i=0; i<times; i++)
{
//generate the permutation
next_permutation(sp_nodes_p.begin(),sp_nodes_p.end());
path_p.clear();
vector<int>::iterator it = sp_nodes_p.begin();
Dijkstra_modify(n,st_node);
cnt += dist[*it];
path.push_back(*it);
//cout<<"st: "<<cnt<<endl;
bool sp_edge_p[maxnum][maxnum];
memcpy(sp_edge_p,sp_edge,sizeof(sp_edge_p));
bool flag = true;
while(1)
{
int tmp=*it;
it++;
if(it==sp_nodes_p.end())
{
break;
}
if(sp_edge_p[tmp][*it])
{
//cout<<"hit : "<<tmp<<"->"<<*it<<" ";
sp_edge_p[*it][tmp] = false;
//refresh the temp
cnt += c[tmp][*it];
//cout<<c[tmp][*it]<<endl;
path_p.push_back(tmp);
path_p.push_back(*it);
}
else
{
for(int j=0; j<n; j++)
{
if(sp_edge_p[tmp][j])
{
flag = false;
break;
}
}
if(!flag)
{
break;
}
Dijkstra_modify(n,tmp);
cnt += dist[*it];
//refresh the temp
//cout<<"short : "<<tmp<<"->"<<*it<<" : ";
//print(*it,tmp);
stack<int> q;
int tmp2=*it;
while(tmp2!=tmp)
{
q.push(tmp2);
tmp2=prev[tmp2];
}
while(q.empty()==0)
{
path_p.push_back(q.top());
q.pop();
}
//cout<<dist[*it]<<endl;
}
}
if(!flag)
{
//cout<<"pass"<<endl;
cnt=0;
continue;
}
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<<tm_node<<endl;
//cout<<"tm :"<<dist[tm_node]<<endl;
if(ans > cnt)
{
path.clear();
ans = cnt;
for(vector<int>::iterator pit =path_p.begin(); pit!=path_p.end(); pit++)
{
if(judge == *pit) continue;
judge=*pit;
path.push_back(*pit);
}
cnt_nodes=path.size();
}
cnt=0;
}
cout<<"distance :"<<ans<<endl;
int judge = st_node;
cout<<"path :"<<st_node<<"->";
for(int i=0; i<cnt_nodes; i++)
{
if(judge == path[i]) continue;
cout<<path[i]<<"->";
judge=path[i];
}
cout<<tm_node<<endl;
if(cnt_nodes>6)
{
cout<<"No optimal solution"<<endl;
}
else
{
cout<<"The optimal solution:"<<endl;
}
cout<<"number of nodes :"<<cnt_nodes+2<<endl;
return 0;
}