题目描述:
有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);
}