忙碌又贪心的泥瓦匠

10347 忙碌又贪心的泥瓦匠
时间限制:1000MS 内存限制:65535K 提交次数:8 通过次数:4
语言: not limited
描述
村里有唯一一个泥瓦匠叫Kemo,很多人需要找Kemo修房子、修灶台、造花园……等,大家可以向Kemo预约修葺的时间和工钱。
现在情况是:
1)Kemo只有一个人,不能同时为两个雇主工作
2)Kemo只有干完一个雇主家的活才可以在接下来的一天切换到另一个雇主家里干活。未干完一份活不可以离开,不可以为多位雇主交叉时间干活
3)Kemo如果不能在预约的时间那天应约的话,这个雇主的这份钱就挣不到了
Kemo比较聪明,他把大家的预约收集好,想让自己忙碌一阵子,赚最多的钱。现在请你为这个忙碌而又贪心的Kemo设计一个思路吧。
输入格式
输入4行:
第一行,一个数字,n,表示n个人向Kemo预约需要修葺(n<=100)
第二行,n个正数,表示这n个人所需完成修葺的时间的起始点。若时间点为8,表示第8天开始
第三行,n个正数,表示这n个人所需完成修葺的工程天数。若天数为3,表示这一工程必须维持3天完成(所有工程都可以在第1000天内完成,即起始点+工期<=1000)
第四行,n个正数,表示这n个人能向Kemo付出的工钱,工钱以每天计
输出格式
输出:忙完这阵子,Kemo最多能挣多少钱?
例如:4个人需要找Kemo修葺,起始时间、工期和每天的工钱分别是:
1 3 8 4
3 2 3 2
5 6 10 7
则:Kemo可以获得的最大收益为:5*3+10*3+7*2 = 59
输入样例
4
1 3 8 4
3 2 3 2
5 6 10 7
输出样例
32
59
Hint
此题标题虽有“贪心”,但勿掉入贪心的陷阱中哦(贪心法是解不了滴)。
每项工程有“起始时间”,“工期”和“工钱数”三个性质。若两个工程的从起始时间到结束都不相冲突,就定义这两个工程为“相容工程”。
做子集树,根结点为第1层,叶节点为n+1层。子集树的第i层结点的两个分支代表第i个工程选或者不选。
用回溯算法搜索这n+1层的完全二叉树。
1)若当前工程和之前已选的工程集合不相容,则剪去该分支,不进行该分支之下的搜索,返回到上层结点。

2)将所有满足相容性的可行的叶节点,计算获得的最大工钱数。


-----------------------------------------------------------

10347    忙碌又贪心的泥瓦匠         (搜索;采用递归的回溯)

#include<iostream>

#include<malloc.h>

using namespace std;

//剪支

template<class Type>

class Loading{

friend Type MaxLoading(Type[],int*,int*,int*,int);

private:

void Backtrack(int i);

int n,*x,*s,*e;

Type *v,sum,bestsum;

};

template<class Type>

void Loading<Type>::Backtrack(int i)

{

int j,flag=0;

if(i>n)

return;

if(1){

for(j=i;j>=1;j--)

if(x[j]==1)

{ flag=1;

if(s[i]>=e[j])

{x[i]=1;break;}

else break;

}

if(flag==0) x[i]=1;

if(x[i]==1)

sum+=(e[i]-s[i])*v[i];

if(sum>bestsum)

bestsum=sum;

if(x[i]==1)//剪支啊

Backtrack(i+1);

if(x[i]==1)

sum-=(e[i]-s[i])*v[i];

x[i]=0;

}

Backtrack(i+1);

}

template<class Type>

Type MaxLoading(Type v[],int* s,int* e,int* x,int n)

{

Loading<Type>X;

X.v=v;

X.x=x;

X.s=s;

X.e=e;

X.sum=0;

X.bestsum=0;

X.n=n;

X.Backtrack(1);

return X.bestsum;

}

int main()

{

int n,i,j,temp,Bsum;

int *v,*e,*s,*x;

do{cin>>n;}while(n>1000||n<0);

s=(int*)malloc((n+1)*sizeof(int));

e=(int*)malloc((n+1)*sizeof(int));

v=(int*)malloc((n+1)*sizeof(int));

x=(int*)malloc((n+1)*sizeof(int));

for(i=1;i<=n;i++)

{cin>>s[i];

x[i]=0;}

for(i=1;i<=n;i++)

do{cin>>e[i];

e[i]+=s[i];

}while(e[i]>1000);

for(i=1;i<=n;i++)

cin>>v[i];

for(i=2;i<=n;i++)

{

for(j=1;j<=i;j++)

if(s[i]<s[j])

{

temp=s[j];s[j]=s[i];s[i]=temp;

temp=e[j];e[j]=e[i];e[i]=temp;

temp=v[j];v[j]=v[i];v[i]=temp;

}

}

Bsum=MaxLoading(v,s,e,x,n);

cout<<Bsum<<endl;

return 0;

}

//VC才能过


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值