POJ 3400 Dropping the stones 深搜,然后加个小优化

Dropping the stones
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 1737 Accepted: 616

Description

You have N stones (1 ≤ N ≤ 10), each stone is characterized by weight pi and cost vi (= 1, ... , N). You should drop these stones by a gutter into one of the two bunkers: A or В.

The mechanism of receiving bunkers switching works as follows. The stones are dropping into one of the bunkers until the weight of this bunker’s content will exceed the weight of stones in other bunker by more than D. Then the gutter switches to the other bunker. At the beginning both bunkers are empty, and the first stone falls into the bunker А.

The task is to collect stones with maximum total cost in bunker B after all stones have been dropped.

Input

The input consists of + 1 lines. The first line contains values N and D separated by one or several spaces. The next lines contain values pi and vi, also separated by spaces. All input data (except N) are integers from 0 to 10000.

Output

The output contains a single line with total cost of stones in the bunker B.

Sample Input

4 2
2 2
2 2
1 1
1 1

Sample Output

3

开始没加优化 本来10^10 的复杂度跑出来是1800ms,  

加了判断A水沟花费总值得判断后, 快了很多,只用了300ms.  

有个同学用的是 next_permutation函数,把所有排列都试了一遍,复杂度应该是10!*10, 跑出来是1200ms .   

有两秒时间,  数据又比较水,所以这题可以比较轻松地用搜索过掉.



题意是有n个石头,每个石头有对应的重量pi, 和对应的 价值 vi;

有两条水沟,, 轮流放石头,  要求B水沟最后的总花费要最大.  每次放可以放任意哪个石头.

开始是在A水沟里放, A的总重量大于 B 水沟重量+D后,  就开始放石头进B ,  如果B水沟总重量大于 A水沟总重量+D,下一次又开始要放石头进A水沟


优化的地方,就是每次搜索完一边  , 就把 计算一下 A水沟的总花费的最小值, 如果下一次搜索过程中,A水沟花费大于或等于 A水沟之前计算出的最小值,显然后面的再搜索下去也是没意义的, 就直接return 掉;





#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int maxx;
int a[20][5];
int n,d;
int vis[20],zong;
int tem[20];
int sum;
int maa(int a,int b)
{
	return a>b?a:b;
}
int mii(int a,int b)
{
	return a<b?a:b;
}
int aans;
void dfs(int num,int diji,int sum1,int sum2,int cost,int cost2)
{
	if(aans<cost2)//优化的地方,,aans 是A水沟 跑出来的 最小值.  如果花费超过他 显然不行.
	{
		return;
	}
	if(num==n)
	{
		maxx=maa(cost,maxx);
		aans=min(aans,sum-cost);
		return;
	}
	for(int i=0;i<n;i++)
	{
		if(vis[i]==0)
		{
			vis[i]=1;
			if(diji==1&&sum1+a[i][0]-sum2>d)
			{
				dfs(num+1,2,sum1+a[i][0],sum2,cost,cost2+a[i][1]);
			}
			else if(diji==2&&sum2+a[i][0]-sum1>d)
			{
				dfs(num+1,1,sum1,sum2+a[i][0],cost+a[i][1],cost2);
			}
			else 
			{
				if(diji==2)
				{
					dfs(num+1,2,sum1,sum2+a[i][0],cost+a[i][1],cost2);
				}
				else
					dfs(num+1,1,sum1+a[i][0],sum2,cost,cost2+a[i][1]);
			}
			vis[i]=0;
		}
	}
	return ;
}

int main()
{
	int i;
	scanf("%d%d",&n,&d);
	maxx=0;
	sum=0;
	aans=1000000000;
	for(i=0;i<n;i++)
	{
		scanf("%d%d",&a[i][0],&a[i][1]);//[0]是 p   [1]是cost v
		sum+=a[i][1];
	}
	memset(vis,0,sizeof(vis));
	dfs(0,1,0,0,0,0);
	printf("%d\n",maxx); 
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值