Problem C. SIRO Challenge JAGain and JAGain Urozero Training Camp, Day 1, DP

Problem C. SIRO Challenge
Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 mebibytes
You are now participating in the Summer Training Camp for Programming Contests with your friend
Jiro, who is an enthusiast of the ramen chain SIRO. Since every SIRO restaurant has its own tasteful
ramen, he wants to try them at as many different restaurants as possible in the night. He doesn’t have
plenty of time tonight, however, because he has to get up early in the morning tomorrow to join a training
session. So he asked you to find the maximum number of different restaurants to which he would be able
to go to eat ramen in the limited time.
There are n railway stations in the city, which are numbered 1 through n. The station s is the nearest
to the camp venue. m pairs of stations are directly connected by the railway: you can move between the
stations ai and bi
in ci minutes in the both directions. Among the stations, there are l stations where a
SIRO restaurant is located nearby. There is at most one SIRO restaurant around each of the stations,
and there are no restaurants near the station s. It takes ei minutes for Jiro to eat ramen at the restaurant
near the station ji
.
It takes only a negligibly short time to go back and forth between a station and its nearby SIRO restaurant.
You can also assume that Jiro doesn’t have to wait for the ramen to be served in the restaurants.
Jiro is now at the station s and have to come back to the station in t minutes. How many different SIRO’s
can he taste?
Input
The first line of the input contains five integers: n for the number of stations, m for the number of directly
connected pairs of stations, l for the number of SIRO restaurants, s for the starting-point station, and
t for the time limit for Jiro (2 ≤ n ≤ 300, 1 ≤ m ≤ 5000, 1 ≤ l ≤ 16, 1 ≤ s ≤ n, 1 ≤ t ≤ 105
). Each
of the following m lines contains three integers: ai and bi for the connected stations, and ci for the time
it takes to move between the two stations (1 ≤ ai
, bi ≤ n, 1 ≤ ci ≤ 1000, ai 6= bi
, (ai
, bi) 6= (aj , bj ) and
(ai
, bi) 6= (bj , aj ) for any i 6= j). Each of the following l lines contains two integers: ji for the station where
a SIRO restaurant is located, and ei for the time it takes for Jiro to eat at the restaurant (1 ≤ ji ≤ n,
1 ≤ ei ≤ 15, ji 6= s, all ji are pairwise distinct). Note that there may be some stations not reachable from
the starting point s.
Output
Output the maximum number of different restaurants where Jiro can go within the time limit

看到 l<=16 ,自然应该想到和二进制有关,也就是想到 状压dp ;
考虑 dp[ i ][ j ];
表示i 状态,目前在 j 餐馆的最大数;
先用 floyd 算法处理每两个点的最短路;
然后 dp 即可;

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<string>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
using namespace std;
#define maxn 200005
#define inf 0x3f3f3f3
#define INF 0x7fffffff
typedef long long ll;
typedef unsigned long long ull;

inline int read()
{
    int x = 0, k = 1; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-')k = -1; c = getchar(); }
    while (c >= '0' && c <= '9')x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    return x * k;
}

int dp[1 << 18][50];
int n, m, l;
int s, t;

int dis[500][500];
int last[50];
int lastT[50];

int main()
{
    //ios::sync_with_stdio(false);
    cin >> n >> m >> l >> s >> t;
    //memset(dis, 0x3f, sizeof(dis));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++)dis[i][j] = inf;
    }
    memset(dp, -1, sizeof(dp));
    for (int i = 0; i < n; i++)dis[i][i] = 0;
    for (int i = 0; i < m; i++) {
        int x, y, z;
        cin >> x >> y >> z;
        dis[x - 1][y - 1] = z;
        dis[y - 1][x - 1] = z;
    }
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
            }
        }
    }
    for (int i = 0; i < l; i++) {
        int x, y;
        cin >> x >> y;
        last[i] = x - 1; lastT[i] = y;
    }
    for (int i = 0; i < l; i++) {
        if (dis[s - 1][last[i]] < inf) {
            dp[1 << i][i] = dis[s - 1][last[i]] + lastT[i];
        }
    }
    int cnt, res = 0;
    for (int i = 0; i < (1 << l); i++) {
        cnt = 0;
        for (int j = 0; j < l; j++)if ((1 << j)&i)cnt++;
        for (int j = 0; j < l; j++) {
            if ((1 << j)&i) {
                int temp = i - (1 << j);
                for (int k = 0; k < l; k++) {
                    if (temp&(1 << k) && dis[last[k]][last[j]] < inf&&dp[temp][k] != -1) {
                        if (dp[i][j] == -1) {
                            dp[i][j] = dp[temp][k] + dis[last[k]][last[j]] + lastT[j];
                        }
                        else
                            dp[i][j] = min(dp[i][j], dp[temp][k] + dis[last[k]][last[j]] + lastT[j]);
                    }
                }
                if (dp[i][j] != -1 && dp[i][j] + dis[last[j]][s - 1] <= t)
                    res = max(res, cnt);
            }
        }
    }
    cout << res << endl;
}


猜你喜欢

转载自blog.csdn.net/qq_40273481/article/details/81710582
今日推荐