1945年,美国的曼哈顿项目引爆了世界上第一颗核弹,从此,全球核武器的数量急剧增加。
如今,CAPCOM®的一位名叫tgy的设计师竟拥有了核武器,想要毁灭世界(?)。然而,我们的舅舅已经提前得知了它的邪恶计划,必须阻止它!
首先,tgy的核武器系统由一些电站组成,每个电站都提供一定的功率值,构成了一个庞大的供电网。想要启动核武器,必须消耗整个供电网一半的电力。所以,我们需要将总计提供一半以上功率的电站关闭,使得电网中的剩余功率低于最初的一半,阻止tgy发射核弹。我们的坦克已经在基地(id为0)做好了准备,对于每个供电站,只有当我们的坦克一直停在那里,我们才能控制它们。假设我们有足够多的坦克,每辆坦克行驶1单位距离花费1单位油。
现在我们的指挥官想知道这次行动的最少油耗。
Input
输入数据的第一行包含一个整数T,表示文件中测试点的数量。
对于每组数据,第一行有两个整数n(1<= n<= 100), m(1<= m<= 10000),指定电站的数量(id为1、2、3…n,基地的id为0),以及站点之间的道路数量(双向)。
接下来的m行,每一行都有三个整数 st(0<= st<= n), ed(0<= ed<= n), dis(0<= dis<= 100),指定起始点、结束点和它们之间的距离。
接下来的n行,每一行都有一个整数pow(1<= pow<= 100),按ID顺序表示各电站的功率。
Output
输出最低的石油成本。
若不存在则输出 "impossible"(不带引号).
Sample Input
2
2 3
0 2 9
2 1 3
1 0 2
1
3
2 1
2 1 3
1
3
Sample Output
5
impossible
思路
用Dijsktra算法或Floyd算法等最短路算法求出 0(基地)到 n(电站)的最短距离,再用01背包
01背包
二维
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
// 当前背包容量装不进第i个物品,则价值等于前i-1个物品
if(j < v[i])
f[i][j] = f[i - 1][j];
// 能装,需进行决策是否选择第i个物品
else
f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);
}
一维
for(int i = 1; i <= n; i++)
{
for(int j = m; j >= v[i]; j--)
f[j] = max(f[j], f[j - v[i]] + w[i]);
}
AC代码
//Floyd
#include <iostream>
#include <cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 110, M = 10010;
int g[N][N];
int dp[M * 2], p[N];
bool st[N];
int n, m, k, dm, v;
int main()
{
scanf("%d", &k);
while (k--)
{
scanf("%d%d", &n, &dm);
memset(dp, 0, sizeof dp);
for (int i = 0; i <= n; i++)
for (int j = 0; j <= n; j++)
if (i == j)
g[i][j] = 0;
else
g[i][j] = INF;
for (int i = 0; i < dm; i++)
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
g[a][b] = g[b][a] = min(g[a][b], w);
}
for (int k = 0; k <= n; k++)
for (int i = 0; i <= n; i++)
for (int j = 0; j <= n; j++)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
m = 0, v = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d", &p[i]);
v += p[i];
if (g[0][i] != INF)
{
m += g[0][i];
}
}
for (int i = 1; i <= n; i++)
{
for (int j = m; j >= g[0][i]; j--)
{
dp[j] = max(dp[j], dp[j - g[0][i]] + p[i]);
}
}
bool flat = false;
int answer;
for (int i = 0; i < m; i++)
{
if (dp[i] > v / 2)
{
answer = i;
flat = true;
break;
}
}
if (flat)
{
printf("%d\n", answer);
}
else
{
puts("impossible");
}
}
return 0;
}
//bellman_ford
#include <iostream>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 110, M = 10010;
int n, m, k, v, dm;
int dist[N], dp[M], p[N];
struct Edge
{
int a, b, w;
} edges[M * 2];
void bellman_ford()
{
memset(dist, INF, sizeof dist);
dist[0] = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 2 * m; j++)
{
int a = edges[j].a, b = edges[j].b, w = edges[j].w;
if (dist[b] > dist[a] + w)
dist[b] = dist[a] + w;
}
}
}
int main()
{
scanf("%d", &k);
while (k--)
{
scanf("%d%d", &n, &m);
memset(dp, 0, sizeof dp);
for (int i = 0; i < m; i++)
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
edges[2 * i] = {a, b, w};
edges[2 * i + 1] = {b, a, w};
}
v = 0, dm = 0;
bellman_ford();
for (int i = 1; i <= n; i++)
{
scanf("%d", &p[i]);
v += p[i];
if (dist[i] != INF)
{
dm += dist[i];
}
}
for (int i = 1; i <= n; i++)
{
for (int j = dm; j >= dist[i]; j--)
{
dp[j] = max(dp[j], dp[j - dist[i]] + p[i]);
}
}
bool flat = false;
int answer;
for (int i = 0; i < dm; i++)
{
if (dp[i] > v / 2)
{
answer = i;
flat = true;
break;
}
}
if (flat)
{
printf("%d\n", answer);
}
else
{
puts("impossible");
}
}
return 0;
}
最短路:鉴于y总