题意:
给定n个城市,n*(n-1)个航线,求在确定的第k天从城市1飞到城市n的最小票价,途中可以经过任意航班可以达到的城市。
这个题的输入是酱的:第一行输入n,k,表示n个城市和确定的k天,然后以下n*(n-1)行,每行先输入当前航班票价循环的天数d,然后依此给出d天票价。
航班的可达关系是:eg,n = 2,第一行代表城市1到2的航班,第2行表示城市2到1的航班...。
具体输入看代码。
解析:
dp[ d ][ i ] 表示d天到达城市i的最小花费,price[ j ][ i ] [ d ] 表示在第d天从城市j到达城市i的费用。
循环的票价用 t = (d - 1) % day[j][i] + 1 来处理。
临界值dp[ 0 ] [ 1 ] = 0 , 余下 = inf。
状态转移方程:dp[ d ] [ i ] = min ( dp[ d ] [ i ] , dp[d - 1] [ j ] + price[ j ] [ i ] [ t ] ).
对于当前天数d,从j地点到达i地点,若前一天从j飞到i的价格小于当前,则更新。
答案为d[k][n]。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#define LL long long
using namespace std;
const int maxn = 10 + 10;
const int maxk = 1000 + 10;
const int inf = 0x3f3f3f3f;
int day[maxk][maxk];
int dp[maxk][maxn];// k days to destination n
int price[maxn][maxn][maxk];
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int n, k;
int ca = 1;
while (~scanf("%d%d", &n, &k))
{
if (n == 0 && k == 0)
break;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (i != j)
{
scanf("%d", &day[i][j]);
for (int d = 1; d <= day[i][j]; d++)
{
scanf("%d", &price[i][j][d]);
}
}
}
}
memset(dp, inf, sizeof(dp));
dp[0][1] = 0;
for (int d = 1; d <= k; d++)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (i != j)
{
int t = (d - 1) % day[j][i] + 1;
if (price[j][i][t] && dp[d - 1][j] != inf)
{
dp[d][i] = min(dp[d][i], dp[d - 1][j] + price[j][i][t]);
}
}
}
}
}
printf("Scenario #%d\n", ca++);
if (dp[k][n] != inf)
printf("The best flight costs %d.\n\n", dp[k][n]);
else
printf("No flight possible.\n\n");
}
return 0;
}