[tyvj1064]新三国争霸(最短路+dp)

44 篇文章 0 订阅

题目:

我是超链接

题解:

枚举i、j,表示时间i到时间j的方案不变动。
f[j]表示前j时间的最少费用。
tt表示i到j方案不变动的最少费用。
k是变动一次需要的军粮数。
f[j]:=min(f[j],f[i]+tt*(j-i)*v+k);
其中tt可以用kruskal算法求出最小生成树求得。

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define INF 1e9
using namespace std;
struct road{int x,y,z,id;}sd[5005];
int n,m,t,v,k,fa[305],r[305][305],f[55];
bool bx[5005][55];
int cmp(road a,road b){return a.z<b.z;}
int find(int x)
{
    if (fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}
int work(int l,int r)
{
    int i,j,cnt=0,len=0;
    for (i=1;i<=n;i++) fa[i]=i;
    for (i=1;i<=m;i++)
    {
        bool fff=false;
        for (j=l;j<=r;j++) if (bx[sd[i].id][j]) {fff=true; break;}
        if (fff) continue;
        int a=find(sd[i].x),b=find(sd[i].y);
        if (a!=b){fa[a]=b;cnt++;len+=sd[i].z;if (cnt==n-1) return len;}
    }
    return INF;
}
int main()
{
    int i,j,p;
    scanf("%d%d%d%d%d",&n,&m,&t,&v,&k);
    for (i=1;i<=m;i++)
    {
        scanf("%d%d%d",&sd[i].x,&sd[i].y,&sd[i].z);
        r[sd[i].x][sd[i].y]=r[sd[i].y][sd[i].x]=i;
        sd[i].id=i;
    }
    sort(sd+1,sd+m+1,cmp);
    scanf("%d",&p);
    for (i=1;i<=p;i++)
    {
        int x,y,t1,t2;
        scanf("%d%d%d%d",&x,&y,&t1,&t2);
        int hh=r[x][y];
        for (j=t1;j<=t2;j++) bx[hh][j]=true;
    }
    memset(f,0x7f,sizeof(f));f[0]=0;
    for (i=1;i<=t;i++)
      for (j=0;j<i;j++)
        f[i]=min(f[i],f[j]+work(j+1,i)*(i-j)*v+k);
    printf("%d",f[t]);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值