Running
Time Limit: 1000MS |
Memory Limit: 65536K |
Total Submissions: 7477 |
Accepted: 2810 |
Description
The cows are trying to become better athletes, so Bessie isrunning on a track for exactly N (1 ≤ N ≤ 10,000) minutes. During each minute,she can choose to either run or rest for the whole minute.
The ultimate distance Bessie runs, though, depends on her'exhaustion factor', which starts at 0. When she chooses to run in minute i, she will run exactly adistance of Di (1 ≤ Di ≤ 1,000) and her exhaustion factorwill increase by 1 -- but must never be allowed to exceed M (1 ≤ M ≤ 500). If she chooses to rest, herexhaustion factor will decrease by 1 for each minute she rests. She cannotcommence running again until her exhaustion factor reaches 0. At that point,she can choose to run or rest.
At the end of the N minute workout, Bessie's exaustionfactor must be exactly 0, or she will not have enough energy left for the restof the day.
Find the maximal distance Bessie can run.
Input
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Line i+1contains the single integer: Di
Output
* Line 1: A single integer representing the largest distanceBessie can run while satisfying the conditions.
SampleInput
5 2
5
3
4
2
10
SampleOutput
9
Source
USACO 2008 January Silver
算法分析:
困了我一下午的题,啊啊啊啊
题意:
这题的题意难以理解,poj直接会误导人,洛谷上的解释还算可以,就是可以有免费的k条边,总花费为自费边最长的那一条边的花费,这里是关键。(被题意坑了好久)
分析:
二分+spfa,二分枚举0~最大边长,跑SPFA,把所有大于mid的边的边权都看作1,其余看作0.若终点的距离大于k,也就是说有不止k条边大于等于mid,无法全部报销,那么成本将大于mid,于是重新枚举mid。假如终点n的距离小于等于mid,那成本能达到mid这么小,于是用mid更新答案,但是要枚举更小的mid值,看成本能不能更小。
算法分析:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define M 15000
int n,m,k,dis[M],vis[M];
vector<int>g[M],w[M];
int spfa(int mid)
{for(int i=0;i<=n;i++)dis[i]=1e9;memset(vis,0,sizeof(vis));queue<int>q;q.push(1);dis[1]=0;vis[1]=1;while(!q.empty()){int i=q.front();q.pop();vis[i]=0;for(int j=0;j<g[i].size();j++){int k=g[i][j];int d;if(w[i][j]<=mid) d=0;//这里有=,不然会答案错误else d=1;if(dis[k]>dis[i]+d){dis[k]=dis[i]+d;if(!vis[k]){vis[k]=1;q.push(k);}}}}return 0;
}
int main()
{while(scanf("%d%d%d",&n,&m,&k)!=EOF){memset(g,0,sizeof(g));memset(w,0,sizeof(w));int maxx=-9999;for(int i=1;i<=m;i++)//这里要从一开始{int a,b,d;scanf("%d%d%d",&a,&b,&d);g[a].push_back(b);//g记录该点连接的点g[b].push_back(a);w[a].push_back(d);w[b].push_back(d);maxx=max(d,maxx);}if(n==1) {cout<<0<<endl;break;}int l=0,r=maxx,mid,ans=1e9;while(l<=r){mid=(l+r)/2;spfa(mid);if(dis[n]>k)//无法报销这么多{l=mid+1;}else //可以报销了,但可能还有更小的{r=mid-1;ans=mid;}}if(ans==1e9)cout<<-1<<endl;elseprintf("%d\n",ans);}return 0;
}