ZOJ3524:Crazy Shopping(拓扑排序+完全背包)

Because of the 90th anniversary of the Coherent & Cute Patchouli (C.C.P), Kawashiro Nitori decides to buy a lot of rare things to celebrate.

Kawashiro Nitori is a very shy kappa (a type of water sprite that live in rivers) and she lives on Youkai MountainYoukai Mountain is a dangerous
place full of Youkai, so normally humans are unable to be close to the mountain. But because of the financial crisis, something have changed. For example, Youkai Mountain becomes available for tourists.

On the mountain there are N tourist attractions, and there is a shop in each tourist attraction. To make the tourists feel more challenging (for example, to collect all kinds
of souvenirs), each shop sells only one specific kind of souvenir that can not buy in any other shops. Meanwhile, the number of the souvenirs which sells in each shop is infinite. Nitori also knows that each kind of souvenir has a weight TWi (in
kilogram) and a value TVi.

Now Nitori is ready to buy souvenirs. For convenience, Nitori numbered the tourist attraction from 1 to N. At the beginning Nitori is located at
the tourist attraction X and there are M roads connect some pairs of tourist attractions, and each road has a length L. However, because Youkai Mountain is very steep, all roads are uni-directional. By the way, for
same strange reason, the roads ensure that when someone left one tourist attraction, he can not arrive at the same tourist attraction again if he goes along the road.

Nitori has one bag and the maximal load is W kilogram. When there are K kilogram things in Nitori‘s bag, she needs to cost K units energy
for walking one unit length road. Of course she doesn‘t want to waste too much energy, so please calculate the minimal cost of energy of Nitori when the value is maximal.

Notice: Nitori can buy souvenir at tourist attraction X, and she can stop at any tourist attraction. Also, there are no two different roads between the same two tourist
attractions. Moreover, though the shop sells different souvenirs, it is still possible for two different kinds of souvenir have the same weight or value.

Input

There are multiple test cases. For each test case:

The first line contains four numbers N (1 <= N <= 600) - the number of tourist attractions, M (1 <= M <= 60000) - the number of roads, W (1
<= W <= 2000) - the load of the bag and X (1 <= X <= N) - the starting point ofNitori.

Then followed by N lines, each line contains two integers which means the shop on tourist attraction i sells the TWi and TVi things
(1 <= TWi <= W, 1 <= TVi <= 10000).

Next, there are M lines, each line contains three numbers, XiYi and Li, which means there is a one-way road
from tourist attraction Xi to Yi, and the length is Li (1 <= Xi,Yi <= N, 1 <= Li <= 10000).

Output

For each test case, output the answer as the description required.

Sample Input

4 4 10 1
1 1
2 3
3 4
4 5
1 2 5
1 3 4
2 4 4
3 4 5

Sample Output

0

题意:
有一个有向无环图,图上有n个点,每个地点有一种占用V空间,价值为W的物品,现在一个人从某点出发,如果背包有C重量的物品,走过路程为K,会消耗C*K的体力,那么在背包容量一定的情况下,我要得到最大的价值需要消耗的最少体力是多少

思路:
先进行一次拓扑排序,根据其排序后的特点,我们只需要按照这个顺序进行完全背包就可以了


#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <math.h>
using namespace std;
struct node
{
    int next,dis;
};

vector<node> a[605];
int n,m,sum,st;
int v[605],w[605],root[605];
int dp[605][2005],tp[605],tem[605],top,len;
int power[605][2005],vis[605];
int max_val,min_pow;

void topoo()//拓扑排序
{
    int i,j;
    len = top = 0;
    for(i = 1; i<=n; i++)
    {
        if(!root[i])
            tem[++top] = i;
    }
    while(top)
    {
        int k = tem[top--];
        tp[++len] = k;
        int end = a[k].size();
        for(i = 0; i<end; i++)
        {
            node ss = a[k][i];
            root[ss.next]--;
            if(!root[ss.next])
                tem[++top] = ss.next;
        }
    }
}
void solve()
{
    max_val = 0;
    int i,j,k;
    vis[st] = 1;
    for(i = 0; i<=sum; i++)//初始化
    {
        power[st][i] = 0;
        if(i>=v[st])
            dp[st][i] = max(dp[st][i],dp[st][i-v[st]]+w[st]);
    }
    max_val = dp[st][sum];
    min_pow = 0;
    for(i = 1; i<=n; i++)
    {
        int x = tp[i];
        if(!vis[x]) continue;
        int l = a[x].size();
        for(j = 0; j<l; j++)
        {
            node sk = a[x][j];
            int y = sk.next;
            vis[y] = 1;
            for(k = 0; k<=sum; k++)//先把x位置的情况与y位置最优的情况比较,选最优的先转移到y位置
            {
                if(dp[x][k]>dp[y][k])
                {
                    dp[y][k] = dp[x][k];
                    power[y][k] = power[x][k]+sk.dis*k;
                }
                else if(dp[x][k]==dp[y][k])
                {
                    if(power[y][k] == -1)
                        power[y][k] = power[x][k]+sk.dis*k;
                    else
                        power[y][k] = min(power[y][k],power[x][k]+sk.dis*k);
                }
            }
            for(k = v[y]; k<=sum; k++)//进行完全背包
            {
                if(dp[y][k]<dp[y][k-v[y]]+w[y])
                {
                    dp[y][k] = dp[y][k-v[y]]+w[y];
                    power[y][k] = power[y][k-v[y]];
                }
                else if(dp[y][k]==dp[y][k-v[y]]+w[y])
                {
                    power[y][k] = min(power[y][k],power[y][k-v[y]]);
                }
            }
            for(k = 0; k<=sum; k++)//寻找答案
            {
                if(dp[y][k]>max_val || (dp[y][k]==max_val && power[y][k]<min_pow))
                {
                    max_val = dp[y][k];
                    min_pow = power[y][k];
                }
            }
        }
    }
}

int main()
{
    int i,j,k;
    while(~scanf("%d%d%d%d",&n,&m,&sum,&st))
    {
        for(i = 1; i<=n; i++)
            scanf("%d%d",&v[i],&w[i]);
        memset(root,0,sizeof(root));
        memset(dp,0,sizeof(dp));
        memset(power,-1,sizeof(power));
        memset(vis,0,sizeof(vis));
        int x,y,z;
        for(i = 0; i<=n; i++)
            a[i].clear();
        for(i = 0; i<m; i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            root[y]++;
            node ss;
            ss.next = y;
            ss.dis = z;
            a[x].push_back(ss);
        }
        topoo();
        solve();
        printf("%d\n",min_pow);
    }

    return 0;
}

时间: 2024-07-31 09:02:15

ZOJ3524:Crazy Shopping(拓扑排序+完全背包)的相关文章

Crazy Shopping(拓扑排序+完全背包)

Crazy Shopping(拓扑排序+完全背包) Because of the 90th anniversary of the Coherent & Cute Patchouli (C.C.P), Kawashiro Nitori decides to buy a lot of rare things to celebrate. Kawashiro Nitori is a very shy kappa (a type of water sprite that live in rivers) a

zoj 3524(拓扑排序+多重背包)(好题)

http://blog.csdn.net/woshi250hua/article/details/7824773 #include <iostream> #include <string> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <algorithm> #include <stack> #

ZOJ3524Crazy Shopping(完全背包+拓扑排序)经典

H - Crazy Shopping Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit Status Description Because of the 90th anniversary of the Coherent & Cute Patchouli (C.C.P), Kawashiro Nitori decides to buy a lot of rare things

ZOJ 3524 Crazy Shopping DAG上的完全背包

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4439 题意: n个点的有向无环图,边有长度,从一个点到另一点消耗背包重量与边长的乘积.每个点卖物品,价值v,重量w,数量无限,给定起点,和背包容量,可以在任意点停止,问最大化所获得价值的情况下需要消耗的最少能量. 分析: 前两天一拙计没想出来,先放着了,今天水了几次才过= =.f[i][j]表示在i点用j的容量所得最大价值,g[i][j]表示同样状态下获得最大价值所需最小能量

ZOJ 3524 Crazy Shopping

Crazy Shopping Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on ZJU. Original ID: 352464-bit integer IO format: %lld      Java class name: Main Because of the 90th anniversary of the Coherent & Cute Patchouli (C.C.P), Kawashiro

hdoj 4324 Triangle LOVE【拓扑排序判断是否存在环】

Triangle LOVE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3566    Accepted Submission(s): 1395 Problem Description Recently, scientists find that there is love between any of two people. For

HDU4324 Triangle LOVE【拓扑排序】

Triangle LOVE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2683    Accepted Submission(s): 1084 Problem Description Recently, scientists find that there is love between any of two people. Fo

HDU 4324 Triangle LOVE (拓扑排序)

Triangle LOVE Problem Description Recently, scientists find that there is love between any of two people. For example, between A and B, if A don't love B, then B must love A, vice versa. And there is no possibility that two people love each other, wh

HDU4324 Triangle LOVE 【拓扑排序】

Triangle LOVE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2455    Accepted Submission(s): 997 Problem Description Recently, scientists find that there is love between any of two people. For