[BZOJ3380] [Usaco2004 Open]Cave Cows 1

题目描述

Description

很少人知道其实奶牛非常喜欢到洞穴里面去探险。
洞窟里有N(1≤N≤100)个洞室,由M(1≤M≤1000)条双向通道连接着它们.每对洞室间
至多只有一条双向通道.有K(1≤K≤14)个洞室,里面放有1捆干草.牛吃1捆干草,体重指数就会增加1.
贪吃的贝茜要到洞窟里面探险.她希望能吃尽量多的干草,但每条通道有一个宽度阈值,如果体重指数超过相应的阈值,贝茜就会被卡祝她从洞窟1出发,体重指数为0.在洞里溜达一圈后,她要返回洞窟1.
那她最多能吃多少捆干草呢?注意,贝茜经过一个洞室,不一定非要吃掉里面的干草.

Input

第1行输入N,M,K,之后K行每行一个整数,表示在这个洞室放有一捆干草;接下来M行每行三个整数,表示一条双向通道的起点终点和宽度阈值.

Output

最多能吃掉的干草数.

Sample Input

6 7 5
1
2
3
4
5
1 2 3
3 6 2
6 2 10
2 4 1
5 1 1
4 5 1
1 6 1

Sample Output

4

题目分析

f[s][i]表示 经过了状态s的关键点, 并且最后到达的是第i个关键点 的情况能不能达到

#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
int n,m,k;
int vis[200];
int f[200][200];
int dp[1<<16][18];
void floyed()
{
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                f[i][j]=max(f[i][j],min(f[i][k],f[k][j]));
}
int num[1<<18],sa[200];
int main()
{   
    scanf("%d%d%d",&n,&m,&k);
    for(int x,i=1;i<=k;i++) 
        scanf("%d",&x),vis[x]=1,sa[++sa[0]]=x;
    for(int i=1;i<=n;i++) f[i][i]=n;
    for(int x,y,c,i=1;i<=m;i++)
        scanf("%d%d%d",&x,&y,&c),f[x][y]=f[y][x]=c;
    floyed();
    for(int i=1;i<(1<<k);i++) num[i]=num[i-(i&-i)]+1;
    for(int i=1;i<=k;i++) 
        if(f[1][sa[i]]) dp[0][i]=dp[1<<(i-1)][i]=1;
    for(int i=0;i<(1<<k);i++)
        for(int j=1;j<=k;j++)
            if(i&(1<<(j-1)))
                for(int z=1;z<=k;z++)
                {
                    if(z==j) continue;
                    if(i&(1<<(z-1))&&f[sa[j]][sa[z]]>=num[i^(1<<(z-1))])
                        dp[i][j]|=dp[i^(1<<(j-1))][z];
                }
    int ans=0;
    for(int i=0;i<(1<<k);i++)
        for(int j=1;j<=k;j++)
            if(dp[i][j]&&num[i]<=f[sa[j]][1])
                ans=max(ans,num[i]);
    printf("%d",ans);
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注