7-1 (20分)
考察:
贪心:最短路,考虑去重边,无穷远
dp:01背包,传统是不超过一定容量求最大价值,本题是不小于一定容量求最小价值。
#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
const int N = 1010;
const int M = 2e6+10;
int a[N], v[N], n, m, s, sum;
ll ma[N][N], d[N], dp[M];
void dij(){
d[s] = 0;
for(int i = 1; i <= n; i++)
{
int x = 0;
for(int j = 1; j <= n; j++)
if(!v[j] && (x==0||d[j]<d[x])) x = j;
v[x] = 1;
for(int j = 1; j <= n; j++)
d[j] = std::min(d[j], d[x]+ma[x][j]);
}
}
int main(){
scanf("%d%d%d", &n, &m, &s);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
ma[i][i] = 0; sum += a[i];
for(int j = i+1; j <= n; j++) ma[i][j] = ma[j][i] = inf;
}
for(int i = 1; i <= m; i++)
{
int x, y; ll z;
scanf("%d%d%lld", &x, &y, &z);
ma[x][y] = ma[y][x] = std::min(ma[x][y], z);
}
for(int i = 1; i <= n; i++) d[i] = ma[s][i];
dij();
for(int i = 0; i <= sum; i++) dp[i] = inf;
dp[0] = 0;
for(int i = 1; i <= n; i++)
{
for(int j = sum; j >= a[i]; j--)
dp[j] = std::min(dp[j], dp[j-a[i]]+d[i]);
}
ll ans = inf;
for(int i = sum/3+1; i <= sum; i++) ans = std::min(ans, dp[i]);
if(ans == inf) printf("\"DIE TWICE.\"\n");
else printf("%lld\n", ans);
return 0;
}
//别着急,慢点交