入住C博客的第一天。。放上自己今天写的水题

重温世界杯

Description

世界杯结束了,意大利人连本带利的收回了法国人6年前欠他们的债,捧起了大力神杯,成就了4星意大利.       
世界杯虽然结束了,但是这界世界杯给我们还是留下许多值得回忆的东西.比如我们听到了黄名嘴的3分钟激情解说,我们懂得了原来可以向同一个人出示3张黄牌,我们还看到了齐达内的头不仅能顶球还能顶人…………       
介于有这么多的精彩,xhd决定重温德国世界杯,当然只是去各个承办世界杯比赛的城市走走看看.但是这需要一大比钱,幸运的是xhd对世界杯的热爱之情打动了德国世界杯组委会,他们将提供xhd在中国杭州和德国任意世界杯承办城市的往返机票,并说服了这些城市在xhd到达这座城市时为他提供一笔生活费以便他在那里参观时用,当参观完时剩余的钱也将留给xhd,但当生活费不够时他们将强行结束xhd的这次德国之行,除了这个,他们还有一个条件,xhd只能根据他们所给的路线参观.比如有3座城市a,b,c,他们给定了a-b-c-a的路线,那么xhd只有3种参观顺序abc,bca,cab.由于各个城市所提供的生活费和在那里的花费都不同,这使xhd很头痛,还好我们事先知道了这笔生活费和花费.请问xhd最多能顺利参观几座城市?      
              

Input

每组输入数据分两行,第一行是一个正整数n(1<=n<=100000),表示有n座城市.接下来的一行按照给定的路线顺序的输出这n个城市的生活费和花费,w1,l1,w2,l2,……,wn,ln,其中wi,li分别表示第i个城市的生活费和花费,并且它们都是正整数.      
              

Output

对应每组数据输出最多能参观的城市数.      
              

Sample Input

    
    
3 3 2 3 4 2 2 3 3 2 3 4 2 3
              

Sample Output

    
    
3 2
 
 
收获:本应该用dp写的,但是我看不懂dp的方式,只好用土方法写,从第一个城市开始走,走到钱变成负时,判断max和sum的大小,后将sum至零,然后从下一个城市开始继续走,当从最后一个城市进入第一个城市后,再碰到负的话就不用继续走了,肯定没有之前的多了。其实就是最长序列,下次找个机会看看dp的算法。
 
 
 
 
 
include<iostream>
#include <cstdio>

using namespace std;
int get[100001];
int cost[100001];
int vis[100001];

int main(){
      int i,j,sum,a,n,s,e,m,max;
	  while(scanf("%d",&n)!=EOF)
	  {
	    for(i=0;i<=n-1;i++)
		{
		  cin>>get[i]>>cost[i];

		}
		s=e=m=sum=max=0;
		while(1)
		{	
			a=m+get[e]-cost[e];			
			if(a<0)
			{
			   if(s>e)
			   { max=sum>max?sum:max; break;}
			   else
			   {   if(s==n-1) { max=sum;break;}
				   s=(e+1);
				   e=s;
				   max=sum>max?sum:max;
				   sum=m=0;
			   }
			
			}
		    else
			{
				if(s==(e+1)%n) { max=n;break;}
			    sum=sum+1;
			    e=(e+1)%n;
			    m=a;
			}
		}
		printf("%d\n",max);

	  }
}

 

鉴于自己正做的赛题是求有条件的最短路,故特地找到这题

这题的限制是要在一定的花费内走最短路

华为挑战赛的条限制是要走过特定的点

应该差不多


准备尝试多种方法


1.小优的DFS加剪枝

剪枝技巧:

建立邻接表而不是邻接矩阵,因为边太多,而且有重边,矩阵是不可以的

当前城市为n时,判断最小值

若下一个城市已走过,则不走

若当前花费大于限制k,不往下走

若当前路程小于已知的最小值,不往下走

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define Road_M 10005
#define City_M 105
#define INF 9999999
struct
{
	int s,d,l,t;
	int next;
}road[Road_M];
int Head[City_M],vis[City_M];
int min_dis,k,n;
void dfs(int now_city,int cost,int now_dis)
{
	int i,ll,dd,tt;
	if(cost>k||now_dis>min_dis)
		return ;
	if(now_city==n)
	{
		if(now_dis<min_dis)
			min_dis=now_dis;
		return ;
	}


	for(i=Head[now_city];i!=-1;i=road[i].next)
	{
		dd=road[i].d;
		ll=road[i].l;
		tt=road[i].t;
		if(vis[dd]==1)
			continue;
		else vis[dd]=1;
		dfs(dd,cost+tt,now_dis+ll);
		vis[dd]=0;
	}
}



int main(void)
{
	int r,i,ss,dd,ll,tt;
	scanf("%d%d%d",&k,&n,&r);
	memset(Head,-1,sizeof(Head));
	memset(vis,0,sizeof(vis));
	for(i=0;i<r;i++)
	{
		scanf("%d%d%d%d",&ss,&dd,&ll,&tt);
		road[i].s=ss;
		road[i].d=dd;
		road[i].l=ll;
		road[i].t=tt;
		road[i].next=Head[ss];
		Head[ss]=i;
	}
	min_dis=INF;
	vis[1]=0;
	dfs(1,0,0);
	if(min_dis!=100000)
		printf("%d\n",min_dis);
	else printf("-1\n");
	return 0;
}



2.

优先队列+BFS

以BFS的形式搜, 优先出路程短或者花费少的,这样第一次遇到终点时,便是答案


#include<iostream>
#include<algorithm>
#include<cmath>
#include <queue>
using namespace std;
#define Road_M 10005
#define City_M 105
#define INF 9999999
struct
{
	int s,d,l,t;
	int next;
}road[Road_M];
int Head[City_M],vis[City_M];
int min_dis,k,n;

struct State
{
   int now_city,cost,road_len;  //最先出队的为最大的
   bool operator < (const struct State a)const
   {
		if(a.road_len==road_len)
			return a.cost<cost;
		return a.road_len<road_len;
   }
};

void bfs()
{
	priority_queue<State>q;
	State sta;
	min_dis=INF;
	int i,e,d,nc,c;
	while(!q.empty())
		q.pop();
	sta.road_len=0;
	sta.now_city=1;
	sta.cost=0;
	q.push(sta);
	while(!q.empty())
	{
		State x,y;
		x=q.top();q.pop();
		nc=x.now_city;
		if(nc==n)
		{
			min_dis=x.road_len;
			break;
		}
		for(i=Head[nc];i!=-1;i=road[i].next)
		{
			c=road[i].t;
			d=road[i].l;
			e=road[i].d;
			if(x.cost+c<=k)
			{
				y.cost=x.cost+c;
				y.now_city=e;
				y.road_len=x.road_len+d;
				q.push(y);
			}
		}
	}
}



int main(void)
{
	int r,i,ss,dd,ll,tt;
	scanf("%d%d%d",&k,&n,&r);
	memset(Head,-1,sizeof(Head));
	memset(vis,0,sizeof(vis));
	for(i=0;i<r;i++)
	{
		scanf("%d%d%d%d",&ss,&dd,&ll,&tt);
		road[i].s=ss;
		road[i].d=dd;
		road[i].l=ll;
		road[i].t=tt;
		road[i].next=Head[ss];
		Head[ss]=i;
	}
	bfs();

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值