C++路径规划与奶牛飞盘(社内测试2)

题目描述:

有n个点,m条无向边,有A,B两个人,初始时刻A在点1,B在点2,他们要走到点n去。A每走一条边,要消耗B单位能量,B每走一条边,要消耗E单位能量。如果A,B相伴走,则只消耗P单位的能量。请问A,B走到点n,最少要消耗多少能量?

输入数据保证1和n,2和n连通。

输入:

第一行包含整数B,E,P,N和M,所有的整数都不超过40000,N>=3.

接下来M行,每行两个整数,表示该无向边连接的两个顶点。

输出:

一个整数,表示最小要消耗的能量。

样例输入:

4 4 5 8 8
1 4
2 3
3 4
4 7
2 5
5 6
6 8
7 8

样例输出:

22

思路分析:

这一道题最困难的地方在于如何找他们相聚的点,其实我们只需要枚举它们相聚的地点再用BFS求A,B到此端点然后再求端点到终点的单源最短路就可以了。

最后我们再用三个数组存储最短路,最后用循环和一个变量找到最小值就可以了。

代码实现:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
int n,ans,x,y,maxn,m,p,b,e,step[40005],dis1[40005],dis2[40005],dis3[40005];
vector <int> G[40005];
void addEdge(int u,int v)
{
    G[u].push_back(v);
    G[v].push_back(u);
}
bool v[40005],v2[40005];
int read()
{
    int x=0,f=1;
    char s=getchar();
    while(s<'0'||s>'9')
    {
        if(s=='-')
            f=-1;
        s=getchar();
    }
    while(s>='0'&&s<='9')
    {
        x*=10;
        x+=s-'0';
        s=getchar();
    }
    return x*f;
}
void bfs(int x,int s)
{
    queue<int>q;
    q.push(x);
    memset(v,0,sizeof(v));
    v[x]=1;
    memset(step,0,sizeof(step));
    while(!q.empty())
    {
        int y;
        y=q.front();
        q.pop();
        for(int i=0;i<G[y].size();i++)
        {
            if(!v[G[y][i]])
            {
                v[G[y][i]]=1;
                q.push(G[y][i]);
                step[G[y][i]]=step[y]+1;
            }
        }
    }
    if(s==1)
    {
        for(int i=0;i<=n;i++)
            dis1[i]=step[i];
    }
    if(s==2)
    {
        for(int i=0;i<=n;i++)
            dis2[i]=step[i];
    }
    if(s==3)
    {
        for(int i=0;i<=n;i++)
            dis3[i]=step[i];
    }
}
int main()
{
    ans=2100000000;
    b=read();
    e=read();
    p=read();
    n=read();
    m=read();
    int x,y;
    for(int i=1;i<=m;i++)
    {
        x=read();
        y=read();
        addEdge(x,y);
    }
    bfs(1,1);
    bfs(2,2);
    bfs(n,3);
    for(int i=1;i<=n;i++)
            if(ans>(dis1[i]*b+dis2[i]*e+dis3[i]*p))
                ans=dis1[i]*b+dis2[i]*e+dis3[i]*p;
    printf("%d",ans);
}

题目:

有n(2<=n<=20)头奶牛在玩飞盘,可是飞盘飞到了高处。现在他们要想办法叠在一起,去取飞盘。飞盘的高度为H(1 <= H <= 1,000,000,000)。给出每头奶牛的重量、高度、强壮度(能够承受的重量),问他们是否够得到,如果能够取到,求它们额外还能承受最多多少重量。(要保证每头奶牛所承受的重量都不超过它的强壮度)。

输入:

输入格式:

第一行包含N和H。

接下来N行,每行三个数,分别表示它的高度、重量和强壮度。所有的数都为正整数。

输出:

输出格式:

如果奶牛的队伍可以够到飞盘,输出还能承受的最大额外重量;否则输出“Mark is too tall”.

输入样例:

4 10
9 4 1
3 3 5
5 5 10
4 4 5

输出样例:

2

思路分析:

这一道题我们可以用贪心这样想,将强壮值+体重较小的牛排在前面,强壮值+体重较大的牛排在后面,为什么?

因为摆在上面的牛的体重必定小于摆在下面的牛的强壮值,所以排在前面的牛的强壮值因当较小(这样才能让队列更高),两个不等式一加就得到了答案。(其实这道题就是编程社排队+DFS

这样我们就能用DFS(暴搜)得到答案。

代码实现:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll n,m,maxn,ans,sumt,sumh;
struct node{
    ll q,h,t;
}s[55];
bool cmp(node x,node y)
{
    return x.q+x.t<y.q+y.t;
}
void dfs(ll x)
{
    if(x>n)
    {
        if(sumh>=m)
            ans=ans>maxn?ans:maxn;
        return;
    }
    if(sumt<=s[x].q)
    {
        ll p=maxn;
        if(s[x].q-sumt<maxn)
            maxn=s[x].q-sumt;
        sumh+=s[x].h;
        sumt+=s[x].t;
        dfs(x+1);
        sumh-=s[x].h;
        sumt-=s[x].t;
        maxn=p;
    }
    dfs(x+1);
}
int main()
{
    ans=-1;
    maxn=9223372036854775807;
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=n;i++)
        scanf("%lld%lld%lld",&s[i].h,&s[i].t,&s[i].q);
    sort(s+1,s+1+n,cmp);
    dfs(1);
    if(ans==-1)
        printf("Mark is too tall");
    else
        printf("%lld",ans);
}

猜你喜欢

转载自blog.csdn.net/weixin_43810158/article/details/85260994
今日推荐