3521. 【NOIP2013模拟11.7B组】道路覆盖

Description

ar把一段凹凸不平的路分成了高度不同的N段,并用H[i]表示第i段高度。现在Tar一共有n种泥土可用,它们都能覆盖给定的连续的k个部分。

对于第i种泥土,它的价格为C[i],可以使得区间[i,min(n,i+k-1)] 的路段的高度增加E[i]。

Tar要设定一种泥土使用计划,使得使用若干泥土后,这条路最低的高度尽量高,并且这个计划必须满足以下两点要求:

(1)每种泥土只能使用一次。

(2)泥土使用成本必须小于等于M。

请求出这个最低的高度最高是多少。

Input

第一行为如上文所示的三个正整数:N,M,K。

接下来N行,每行3个如上文所示的正整数H[i],E[i],C[i]。

Output

输出有且只有一个数字,为最底部分的高度的最大值

Sample Input

4 20 1

1 3 5

1 7 3

4 6 9

3 5 13

Sample Output

3

Data Constraint

对于30%的数据:N≤20。

对于100%的数据:1≤K≤11,1≤N≤100,0≤M,H[i],E[i],C[i]≤1000000。

Solution

二分+状态压缩DP:

二分枚举最低的高度(设为M),接下来我们考虑判断合法性:设f[i][j]表示在做到底i位,前k位(包括i)选或不选的状态为j的最小金钱代价,那么只要存在状态x使得f[n][x]≤M,那么就说明这个高度是合法的。注意对于一位i只由它的前k位得到,那么就是说f[i][j]由它的前k位得到,所以j所表示的状态只有k位。k的范围是极小的所以不会超时;然后再考虑状态的转移:首先我们要从转移到i+1,因为j这个状态是i+1的前面的k位得来的,也就是i前面的k-1位和i,因为只有这些点才能对第i+1位产生影响,那么我们就枚举一个j的状态,然后对于每个状态将选的点对i+1高度的贡献和求出来,即将前k位选了的泥土的e[i]的和统计出来,然后我们就有两中情况转移:

        第一种:第i+1位不选:f[i+1][第i+1位不选的状态]=min(f[i+1][第i+1位不选的状态],f[i][j]);

        第二种:第i+1位选:f[i+1][第i+1位选的状态]=min(f[i+1][第i+1位选的状态],f[i][j]+选这个泥土的花费);

注意,这两种转移都要满足选或不选后第i+1位泥土的高度是大于当前的M的。

 

Code1

#include
#include
#include
#include
#define N 120
using namespace std;
int l,r,mid,ans,n,m,k,s,x,a,h[N],e[N],c[N],f[N][1<<12];
int dp(int x){
	memset(f,127,sizeof(f));
	f[0][0]=0;
	for(int i=0;i<=n-1;i++){
		for(int j=0;j<=(1<>=1;}
			if(s+h[i+1]>=x) f[i+1][(j<<1)&((1<=x) f[i+1][((j<<1)+1)&((1<>1;
		if(dp(mid)){ans=mid;l=mid+1;}
		else{r=mid-1;}
	}
	printf("%d\n",ans);
	return 0;
}

Code2 

#include
#include
#include
using namespace std;
int n,m,k,e[200],h[200],c[200],f[200][5000],l,r,ans,mid,i;
bool dp(int x){
	memset(f,127,sizeof(f));
	f[0][0]=0;
	int i,j,l,sum;
	for (i=0;i0;l--)  
					if ((1<=x)
					f[i+1][j>>1]=min(f[i+1][j>>1],f[i][j]);
				if (sum+h[i+1]+e[i+1]>=x)
					f[i+1][(j>>1)|(1<<(k-1))]=min(f[i+1][(j>>1)|(1<<(k-1))],f[i][j]+c[i+1]);
			}
	}
	for (int i=0;i<(1<

 



作者:zsjzliziyang 
QQ:1634151125 
转载及修改请注明 
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/83272408

 

你可能感兴趣的:(题目,二分)