Bzoj 3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一

3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 64  Solved: 37
[Submit][Status][Discuss]

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

floyd+状压dp

n<=100所以直接先用floyd预处理要从i到j最多能吃到多胖

f[s][i]表示状态s下到第i个有宝藏的地方,是否能拿到所有s中的宝藏

当然最后还要考虑dis[id[i]][1]是否大于s状态下的宝藏数,取较小值就是答案了

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,K,f[1<<14][15],ans,dis[110][110],id[15];
int main(){
    scanf("%d%d%d",&n,&m,&K);//M条双向通道,K个洞室,里面放有1捆干草 
    for(int i=1;i<=K;i++)scanf("%d",&id[i]);
    int x,y,z;
    for(int i=1;i<=n;i++)dis[i][i]=0x3f3f3f3f;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        dis[x][y]=dis[y][x]=z;
    }
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j&&i!=k&&j!=k){
                    if(dis[i][j]!=0x3f3f3f3f)dis[i][j]=max(dis[i][j],min(dis[i][k],dis[k][j]));
                    else dis[i][j]=min(dis[i][k],dis[k][j]);
                }
    int N=(1<<K);
    for(int i=1;i<=K;i++)f[(1<<(i-1))][i]=1;
    for(int s=1;s<N;s++){
        int num=0;
        for(int i=1;i<=K;i++)if(s&(1<<(i-1)))num++;
        for(int i=1;i<=K;i++)
            if(s&(1<<(i-1)))
            for(int j=1;j<=K;j++)
                if((!(s&(1<<(j-1))))&&num<=dis[id[i]][id[j]])f[s^(1<<(j-1))][j]|=f[s][i];
        for(int i=1;i<=K;i++)
            if((s&(1<<(i-1)))&&f[s][i])
                ans=max(ans,min(dis[id[i]][1],num));
    }
    printf("%d",ans);
}

 

posted @ 2017-05-07 20:20  Echo宝贝儿  阅读(634)  评论(3编辑  收藏  举报