nyoj 三国志 (Dijkstra + 01背包)

。。。 总是没思路  真要命

注意两点之间可能有多条权值不同的路径,不过只要在输入时取最小值就好了。。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<string>
 6 #include<queue>
 7 #include<algorithm>
 8 #include<map>
 9 #include<iomanip>
10 #include<climits>
11 #include<string.h>
12 #include<cmath>
13 #include<stdlib.h>
14 #include<vector>
15 #include<set>
16 #define INF 1e7
17 #define MAXN 100010
18 #define maxn 50
19 #define maxm 1000
20 #define Mod 1000007
21 using namespace std;
22 typedef long long LL;
23
24
25 int T;
26 int s, n, m;
27 int a, b, c;
28 int v[110];
29 int G[110][110];
30 int dist[1000010];
31 int vis[110];
32 int dp[1000010];
33
34 void Dijkstra()
35 {
36     for (int i = 0; i <= n; ++i)
37         dist[i] = G[0][i],vis[i] = 0;
38     int pos, min;
39     vis[0] = 1;
40     dist[0] = 0;
41     for (int i = 1; i <= n; ++i) {
42         min = INF;
43         for (int j = 1; j <= n; ++j) {
44             if (!vis[j] && min > dist[j]) {
45                 pos = j;
46                 min = dist[j];
47             }
48         }
49         vis[pos] = 1;
50         for (int j = 1; j <= n; ++j) {
51             if (!vis[j] && dist[j] > dist[pos] + G[pos][j])
52                 dist[j] = dist[pos] + G[pos][j];
53         }
54     }
55 }
56
57 void bag01()
58 {
59     for (int i = 1; i <= n; ++i)
60         for (int j = s; j >= dist[i]; --j)
61             dp[j] = max(dp[j - dist[i]] + v[i],dp[j]);
62 }
63
64 void run()
65 {
66     scanf("%d%d%d", &s, &n, &m);
67     memset(v,0,sizeof(v));
68     memset(dp,0,sizeof(dp));
69     for (int i = 0; i <= n; ++i)
70         for (int j = 0; j <= n; ++j)
71             G[i][j] = INF;
72     for (int i = 0; i < m; ++i) {
73         scanf("%d%d%d", &a, &b, &c);
74         if (c < G[a][b])
75             G[a][b] = G[b][a] = c;
76     }
77     for (int i = 1; i <= n; ++i)
78         scanf("%d",&v[i]);
79     Dijkstra();
80     bag01();
81     printf("%d\n",dp[s]);
82 }
83 int main()
84 {
85     scanf("%d", &T);
86     while (T--)
87         run();
88     return 0;
89 }
时间: 2024-10-14 06:45:14

nyoj 三国志 (Dijkstra + 01背包)的相关文章

hdu3339 In Action(Dijkstra+01背包)

1 /* 2 题意:有 n 个站点(编号1...n),每一个站点都有一个能量值,为了不让这些能量值连接起来,要用 3 坦克占领这个站点!已知站点的 之间的距离,每个坦克从0点出发到某一个站点,1 unit distance costs 1 unit oil! 4 最后占领的所有的站点的能量值之和为总能量值的一半还要多,问最少耗油多少! 5 6 */ 7 8 /* 9 思路:不同的坦克会占领不同的站点,耗油最少那就是路程最少,所以我们先将从 0点到其他各点的 10 最短距离求出来!也就是d[i]的

nyoj 1091 还是01背包(超大数)

nyoj 1091 还是01背包 描述 有n个重量和价值分别为 wi 和 vi 的物品,从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值 1 <= n <=40 1 <= wi <= 10^15 1 <= vi <= 10^15 1 <= W <= 10^15 分析:在做的时候毫无头绪,在网上看了其他大神的博客才AC了,数据超大无法使用之前的思路(超时且dp数组开不了这么大),但是由本题条件可知n的值非常小,可用递归配合剪枝解题 代码:

NYOJ 1091 超大01背包(折半枚举)

这道题乍一看是普通的01背包,最最基础的,但是仔细一看数据,发现普通的根本没法做,仔细观察数组发现n比较小,利用这个特点将它划分为前半部分和后半部分这样就好了,当时在网上找题解,找不到,后来在挑战程序设计上找到了这个题,就拿来引用一下 挑选物品的方法总从2^n中,直接枚举肯定不行,因为n最大为40,但是如果n为20就可以了,这时候就要用到折半枚举,先枚举前一半,在枚举后一半.先把前把部分的选取方法对应的重量和价值总和记为w1, v1,这样后半部分寻找w2 <= W - w1时 使v2最大的选取方

nyoj 203 三国志(最短路加01背包)

三国志 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描述 <三国志>是一款很经典的经营策略类游戏.我们的小白同学是这款游戏的忠实玩家.现在他把游戏简化一下,地图上只有他一方势力,现在他只有一个城池,而他周边有一些无人占的空城,但是这些空城中有很多不同数量的同种财宝.我们的小白同学虎视眈眈的看着这些城池中的财宝. 按照游戏的规则,他只要指派一名武将攻占这座城池,里面的财宝就归他所有了.不过一量攻占这座城池,我们的武将就要留守,不能撤回.因为我们的小白手下有无数的武将,

nyoj 860 又见01背包 【另类01背包】

分析: 首先这道题不能当做普通的01背包问题,因为W <= 10^9,开不了,那么大的数组,肯定有其他的思路,观察一下我们知道价值v小的很,最大100, 那我们就可以利用这一点,拿价值 之和作为原来的质量之和, 但是有一点要注意:因为题意是要在质量不超过W的范围内,找出最大的价值,我们现在是以最大的价值求质量,那么仔细分析一下,我们就能想明白,要以某价值i的背包存放尽量小的质量,这样反过来分析一下就可以知道,较小的质量有个较大的价值序号,这样完全满足题意了, 最后还有一点,就是价值背包的每一个(

背包 [NYOJ 860] 又见01背包

又见01背包 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述     有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W 的物品,求所有挑选方案中物品价值总和的最大值. 1 <= n <=100 1 <= wi <= 10^7 1 <= vi <= 100 1 <= W <= 10^9 输入 多组测试数据. 每组测试数据第一行输入,n 和 W ,接下来有n行,每行输入两个数,代表第i个物品的wi 和

NYOJ 654喜欢玩warcraft的ltl(01背包/常数级优化)

传送门 Description ltl 非常喜欢玩warcraft,因为warcraft十分讲究团队整体实力,而他自己现在也为升级而不拖累团队而努力. 他现在有很多个地点来选择去刷怪升级,但是在每一个地点他都要买上充足的补给和合适的道具,以免在刷怪的时候被怪物反杀了,每一个地点的怪物打完了就没有了(还居然不掉金钱跟装备),而且他只要选定了地点就一定会刷完该地点全部的怪物,同时获得对应的经验值.现在ltl 能给出每一个地点用来买补给和道具的钱和打完全部怪物所能获得的经验,但是他所拥有的钱是一定的.

NYOJ 题目1091 还是01背包(二分,超大01背包)

还是01背包 时间限制:10000 ms  |  内存限制:228000 KB 难度:5 描述 有n个重量和价值分别为 wi 和 vi 的物品,从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值. 输入 多组测试数据. 每组测试数据第一行输入n 和 W ,接下来有n行,每行输入两个数,代表第i个物品的wi 和 vi. 1 <= n <=40 1 <= wi <= 10^15 1 <= vi <= 10^15 1 <= W <= 10^15

NYOJ(325)+NYOJ(456),01背包

题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=325 http://acm.nyist.net/JudgeOnline/problem.php?pid=456 太久没有接触DP了,分类把这个题目分到了搜索,其实是01背包,有意思的是这里的价值也是重量,我最多装sum/2,那么每个邮票的价值也就变成了重量,并且要尽可能的装满,价值也是价值的含义 两道题几乎一样. #include <stdio.h> #include <mat