标题:[求助]北大一道贪心题[已解决,谢谢大家]
只看楼主
davidloves
Rank: 1
等 级:新手上路
帖 子:137
专家分:0
注 册:2007-1-6
得分:0 

还是我来说吧,嘿嘿我理解了LS的算法了
是这样的:
第一次到d,然后考虑d前面全部的加油站,为什么要考虑呢?这是因为还没到终点。
由于c最多,所以要考虑在c停下加油,于是我们就有在c,d的油了,顺序是先在c加后在d加,然后我们就可以到达比e更远的地方(距离d 14,设为f点)
如果还没有到终点
则考虑
f点以前所有的加油站中油最多的,当然,已经加了的要排除(c, d), 然后就一直这样循环下去


2007-10-14 22:07
davidloves
Rank: 1
等 级:新手上路
帖 子:137
专家分:0
注 册:2007-1-6
得分:0 
以下是引用crackerwang在2007-10-14 22:05:25的发言:
我感觉我这样做应该也没有错啊!
思路就是走到第i个站点的时候先看看到第i-1个的时候油还够不够第i个,不够就从前面没取的站点中去油最多的一个
如果够就算了
WA 三次了

#include<stdio.h>
#define inf 6000000
int a[100100][2];
int heap[100100],m;
void shiftup(int l)
{
int i,j,temp;
temp=heap[l];
i=l;
j=i/2;
while(j>=1)
{
if(heap[j]<temp)
{
heap[i]=heap[j];
i=j;
j/=2;
}
else
{
heap[i]=temp;
return ;
}
}
heap[i]=temp;
}
void shiftdown(int l)
{
int i,j,temp;
temp=heap[l];
i=l;
j=i*2;
while(j<m)
{
if(j+1<m&&heap[j+1]>heap[j]) j++;
if(heap[j]>temp)
{
heap[i]=heap[j];
i=j;
j*=2;
}
else
{
heap[i]=temp;
return ;
}
}
heap[i]=temp;
}
int main()
{
int n,i,j,k;
int l,p;
int cnt;
int flag;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++) scanf("%d%d",&a[i][0],&a[i][1]);
scanf("%d%d",&l,&p);
cnt=0;
j=1;
heap[1]=-1;
m=2;
flag=1;
for(i=n-1;i>=0;i--)
{
while(p<l-a[i][0])
{
if(heap[1]==-1)
{
flag=0;
goto line;
}
p+=heap[1];
heap[1]=-1;
shiftdown(1);
cnt++;
}
heap[m]=a[i][1];
shiftup(m);
m++;
}
line:;
if(flag==0) printf("-1\n");
else printf("%d\n",cnt);
}
}

还是说算法吧,这样看代码很难看的

[此贴子已经被作者于2007-10-14 22:09:20编辑过]


2007-10-14 22:08
crackerwang
Rank: 3Rank: 3
等 级:新手上路
威 望:8
帖 子:833
专家分:0
注 册:2007-2-14
得分:0 

就是走到第i个点的时候先看到第i-1个点的时候油剩下的还够不够到第i个点能就算了.
不能就从前面经过的点中,且没有取的点中取最大的直到能到i点为止要是到不了就是-1了..


其实题目很简单的
可以简化成给你一串数字 a1,a2,a3,a4...
让你从前i个数中取出最少的个数使得和大于某个值就可以了..


2007-10-14 22:16
crackerwang
Rank: 3Rank: 3
等 级:新手上路
威 望:8
帖 子:833
专家分:0
注 册:2007-2-14
得分:0 
发现问题了..
数据不是顺序的

2007-10-14 22:17
cobby
Rank: 1
等 级:新手上路
威 望:1
帖 子:565
专家分:0
注 册:2007-7-11
得分:0 
以下是引用davidloves在2007-10-14 22:07:11的发言:

还是我来说吧,嘿嘿我理解了LS的算法了
是这样的:
第一次到d,然后考虑d前面全部的加油站,为什么要考虑呢?这是因为还没到终点。
由于c最多,所以要考虑在c停下加油,于是我们就有在c,d的油了,顺序是先在c加后在d加,然后我们就可以到达比e更远的地方(距离d 14,设为f点)
如果还没有到终点
则考虑
f点以前所有的加油站中油最多的,当然,已经加了的要排除(c, d), 然后就一直这样循环下去

我就是想知道这个顺序是怎么通过贪心得到的,如果事先(车到d站前)能知道正确的加油顺序那问题真的解决了。


努力成为菜鸟!
2007-10-15 08:27
cobby
Rank: 1
等 级:新手上路
威 望:1
帖 子:565
专家分:0
注 册:2007-7-11
得分:0 
以下是引用Eastsun在2007-10-14 21:58:03的发言:
...
你还是没弄清楚我的算法.
我考虑d后再考虑a,b,c并不表示还需要吧车开回去加油!

你还是看代码吧.
或者你能给出一个数据用我的代码得到错误的结果.

不把车开回去加油?那车在d站不是哪里也去不了了吗?

还是说算法把,代码看着累,而且同一算法的代码也各有不同的呵。希望能讨论下呵。


努力成为菜鸟!
2007-10-15 08:29
crackerwang
Rank: 3Rank: 3
等 级:新手上路
威 望:8
帖 子:833
专家分:0
注 册:2007-2-14
得分:0 
总算是过了..
题目数据还是有点陷阱..比如说可能在起点就有站..什么的

2007-10-15 10:36
davidloves
Rank: 1
等 级:新手上路
帖 子:137
专家分:0
注 册:2007-1-6
得分:0 

我也AC 了
[CODE]/*
*Author: David Hu
*Organization:Harbin Institute of Technology
*Date: From 2007-10-14 21:19:18 to 2007-10-16 18:22:19
*Description: acm.hit.edu.cn Problem 2051
*/
#include <stdio.h>
#include <stdlib.h>
struct node
{
int dis; /* the distance*/
int fuel;
struct node* next;
};
typedef struct node NODE;
typedef struct node* NODE_PTR;
void Create(NODE_PTR*); /* create a link*/
void Get_info_sort(NODE_PTR); /* get all the infomation of the stops and sort as down*/
void Drive (NODE_PTR, NODE_PTR); /* to caculate the result*/
void Insert (NODE_PTR, NODE_PTR); /* insert some link and sort as down*/
int main (void)
{
int s_num; /* the number of stops*/
NODE_PTR head_d, head_f; /* the heads of down sequence distance link and fuel link*/
while(scanf("%d", &s_num) == 1) /* end of run at the end of file*/
{
Create(&head_d);
Create(&head_f);
while(s_num--)
{
Get_info_sort(head_d); /* get all the infomation of the stops and sort as down*/
}
Drive(head_d, head_f);
}
return 0;
}
void Create (NODE_PTR* start_ptr)
{
*start_ptr = (NODE_PTR)malloc(sizeof(NODE) * 1);
(*start_ptr) -> next = NULL;
}
void Get_info_sort (NODE_PTR start_ptr)
{
NODE_PTR new_p, p;
new_p = (NODE_PTR)malloc(sizeof(NODE) * 1);
scanf ("%d%d", &new_p -> dis, &new_p -> fuel);
p = start_ptr;
while(p -> next && p -> next -> dis > new_p -> dis)
{
p = p -> next;
}
new_p -> next = p -> next;
p -> next = new_p;
}
void Drive (NODE_PTR start_ptr_d, NODE_PTR start_ptr_f)
{
int pre_d, pre_f; /* the present distance to the town and the present fuel left*/
int hold, counter = 0;
NODE_PTR p, q;
scanf ("%d%d", &pre_d, &pre_f);
if (start_ptr_d -> next && start_ptr_d -> next -> dis == pre_d)
{
pre_f += start_ptr_d -> next -> fuel;
start_ptr_d = start_ptr_d -> next;
}
hold = pre_d - pre_f;
while(hold > 0)
{
counter++;
p = start_ptr_d;
while(p -> next && p -> next -> dis >= hold)
{
q = (NODE_PTR)malloc(sizeof(NODE) * 1);
q -> dis = p -> next -> dis;
q -> fuel = p -> next -> fuel;
Insert(start_ptr_f, q);
p = p -> next;
free(start_ptr_d);
start_ptr_d = p;
}
if (start_ptr_f -> next == NULL)
{
printf ("-1\n");
return;
}
else
{
hold -= start_ptr_f -> next -> fuel;
start_ptr_f = start_ptr_f -> next;
}
}
printf ("%d\n", counter);
}
void Insert (NODE_PTR start_ptr, NODE_PTR new_p)
{
NODE_PTR p;
p = start_ptr;
while(p -> next && p -> next -> fuel > new_p -> fuel)
{
p = p -> next; /* move to next node*/
}
new_p -> next = p -> next; /* link the new node*/
p -> next = new_p;
}[/CODE]



2007-10-15 18:48
yuerhb
Rank: 1
等 级:新手上路
威 望:1
帖 子:241
专家分:0
注 册:2007-6-1
得分:0 

学编程。。。。再难也得上!!!
2007-10-16 13:28
nuciewth
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:我爱龙龙
等 级:贵宾
威 望:104
帖 子:9786
专家分:208
注 册:2006-5-23
得分:0 
应该可以用递推来做.

倚天照海花无数,流水高山心自知。
2007-10-16 13:59



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-177520-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.125128 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved