hdu 3339 In Action 背包+flyod

来源:互联网 发布:阿里云备案核验单下载 编辑:程序博客网 时间:2024/06/06 01:30

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3339

题意:

给你一个图,每个点都有权值,然后让你派出多辆坦克,破环至少占权值一半的城市,派出坦克的代价就是从0点到那些城市的距离
求最少代价

题解:

点数很少,注意有重边
跑一发flyod,然后背包dp

代码:

#include <bits/stdc++.h>using namespace std;typedef long long ll;#define MS(a) memset(a,0,sizeof(a))#define MP make_pair#define PB push_backconst int INF = 0x3f3f3f3f;const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;inline ll read(){    ll x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}//////////////////////////////////////////////////////////////////////////const int maxn = 100+10;int d[maxn][maxn],d1[maxn],dp[11000],power[maxn];int main(){    int T = read();    while(T--){        int n,m;scanf("%d%d",&n,&m);        for(int i=0; i<=n; i++)            for(int j=0; j<=n; j++)                d[i][j] = INF;        for(int i=0; i<m; i++){            int u,v,w; scanf("%d%d%d",&u,&v,&w);            d[u][v] = d[v][u] = min(d[u][v],w);        }        ll aim = 0;         for(int i=1; i<=n; i++){            power[i] = read();            aim += power[i];        }        for(int k=0; k<=n; k++)            for(int i=0; i<=n; i++)                for(int j=0; j<=n; j++)                    d[i][j] = min(d[i][j],d[i][k]+d[k][j]);        ll sum = 0;        for(int i=0; i<=n; i++)            if(d[0][i] < INF)                sum += d[0][i];        MS(dp);        for(int i=1; i<=n; i++)            for(int j=sum; j>=d[0][i]; j--)                dp[j] = max(dp[j],dp[j-d[0][i]]+power[i]);        ll ans = INF;        for(int i=0; i<=sum; i++)            if(dp[i]>=(aim/2+1)){                ans = i;                break;            }        if(ans == INF)            cout << "impossible\n";        else            cout << ans << endl;    }    return 0;}
0 0