【发布时间】:2015-11-02 17:38:22
【问题描述】:
所以,我正在解决以下问题:http://www.spoj.com/problems/ROADS/en/
以数字 1 ... N 命名的 N 个城市与单向道路相连。每条道路都有两个与之相关的参数:道路长度和道路需要支付的通行费(以硬币数量表示)。鲍勃和爱丽丝曾经住在城市 1。在注意到爱丽丝在他们喜欢玩的纸牌游戏中作弊后,鲍勃与她分手并决定搬走 - 到城市 N。他想尽快到达那里可能,但他缺钱。我们想帮助 Bob 找到他有钱可以负担的从城市 1 到城市 N 的最短路径。
输入
输入以测试用例的数量 t 开始。然后是 t 个测试用例。每个测试用例的第一行包含整数 K,0
输出
对于每个测试用例,输出一行包含从城市 1 到城市 N 的最短路径的总长度,其总通行费小于或等于 K 个硬币。如果该路径不存在,则输出-1。
现在,我所做的是,我尝试使用 djikstra 的算法,如下所示:
我不是只有一个节点作为状态,而是 节点和硬币作为一种状态,然后应用dijkstra。 长度是状态之间的权重。 我在不超过总硬币的情况下最小化长度。
我的代码如下:
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
class node
{
public:
int vertex;
int roadlength;
int toll;
};
int dist[101][101]; // for storing roadlength
bool visited[101][10001];
int cost[101][101]; // for storing cost
int ans[101][10001]; // actual distance being stored here
void djikstra(int totalcoins, int n);
bool operator < (node a, node b)
{
if (a.roadlength != b.roadlength)
return a.roadlength < b.roadlength;
else if (a.toll != b.toll)
return a.toll < b.toll;
return a.vertex < b.vertex;
}
int main (void)
{
int a,b,c,d;
int r,t,k,n,i,j;
cin>>t;
while (t != 0)
{
cin>>k>>n>>r;
for (i = 1; i <= 101; i++)
for (j = 1; j <= 101; j++)
dist[i][j] = INT_MAX;
for (i = 0; i <= n; i++)
for (j = 0; j <= k; j++)
ans[i][j] = INT_MAX;
for ( i = 0; i <= n; i++ )
for (j = 0; j <= k; j++ )
visited[i][j] = false;
for (i = 0; i < r; i++)
{
cin>>a>>b>>c>>d;
if (a != b)
{
dist[a][b] = c;
cost[a][b] = d;
}
}
djikstra(k,n);
int minlength = INT_MAX;
for (i = 1; i <= k; i++)
{
if (ans[n][i] < minlength)
minlength = ans[n][i];
}
if (minlength == INT_MAX)
cout<<"-1\n";
else
cout<<minlength<<"\n";
t--;
}
cout<<"\n";
return 0;
}
void djikstra(int totalcoins, int n)
{
set<node> myset;
myset.insert((node){1,0,0});
ans[1][0] = 0;
while (!myset.empty())
{
auto it = myset.begin();
myset.erase(it);
int curvertex = it->vertex;
int a = it->roadlength;
int b = it->toll;
if (visited[curvertex][b] == true)
continue;
else
{
visited[curvertex][b] = true;
for (int i = 1; i <= n; i++)
{
if (dist[curvertex][i] != INT_MAX)
{
int foo = b + cost[curvertex][i];
if (foo <= totalcoins)
{
if (ans[i][foo] >= ans[curvertex][b] + cost[curvertex][i])
{
ans[i][foo] = ans[curvertex][b] + cost[curvertex][i];
myset.insert((node){i,ans[i][foo],foo});
}
}
}
}
}
}
}
现在,我有两个疑问:
-
首先,对于问题的第一个给定测试用例,我的输出不正确,即
Sample Input:2 5 6 7 1 2 2 3 2 4 3 3 3 4 2 4 1 3 4 1 4 6 2 1 3 5 2 0 5 4 3 2 0 4 4 1 4 5 2 1 2 1 0 2 3 1 1 3 4 1 0 Sample Output: 11 -1
我的输出结果是4 -1,这对于第一个测试用例来说是错误的。我哪里错了?
- 如何处理具有多个边缘的情况?也就是问题提到,
Notice that different roads may have the same source and destination cities.这种情况怎么处理?
【问题讨论】:
-
您在使用调试器单步执行代码时观察到了什么?
-
这不是和你刚才问的一样的数学题(只是不同的单词问题和不同的输入格式)吗?
-
@JSF,是的,因此我使用了相同的方法,但是我得到了一个 WA,我不知道为什么,而且我无法处理拥有的特定条件多个边缘。连这样一个简单的问题我都做不了,我感到很遗憾。 :(
-
@hans 首先,对于问题的第一个给定测试用例,我的输出不正确 -- 我哪里出错了? -- 嗯...为什么不调试您的代码?输出不正确并修复它是学习如何编写程序的一部分。
-
看起来您在代码的不同部分以不同的方式使用您的
ans数组,很不清楚您希望ans的索引意味着什么。即对于这条线ans[i][foo] = ans[curvertex][b] + cost[curvertex][i];,看起来您希望它是一个成本,其中 i 是您的目的地,而 foo 是您的成本?这没有多大意义。但是在这里minlength = ans[n][i];您似乎希望它输出最小长度?我认为如果您解决此问题,您的代码中的主要问题将得到解决