TYZ 8/23 道路覆盖
来源:互联网 发布:怎样找淘宝客推广 编辑:程序博客网 时间:2024/05/16 09:47
道路覆盖
(cover.cpp/c/pas)
【问题描述】
Tar把一段凹凸不平的路分成了高度不同的N段,并用H[i]表示第i段高度。现在Tar一共有n种泥土可用,它们都能覆盖给定的连续的k个部分。
对于第i种泥土,它的价格为C[i],可以使得区间[i,min(n,i+k-1)]的路段的高度增加E[i]。
Tar要设定一种泥土使用计划,使得使用若干泥土后,这条路最低的高度尽量高,并且这个计划必须满足以下两点要求:
(1)每种泥土只能使用一次。
(2)泥土使用成本必须小于等于M。
请求出这个最低的高度最高是多少。
【输入格式】
第一行为如上文所示的三个正整数:N,M,K。
接下来N行,每行3个如上文所示的正整数H[i],E[i],C[i]。
【输出格式】
输出有且只有一个数字,为最底部分的高度的最大值
【样例输入】
4 20 1
1 3 5
1 7 3
4 6 9
3 5 13
【样例输出】
3
【数据范围】
对于30%的数据:N≤20。
对于100%的数据:1≤K≤11,1≤N≤100,0≤M,H[i],E[i],C[i]≤1000000。
看到这个问题之后,想都没想就蛮力搜索,然后拿了40/100,看着大数据被卡了20ms.,痛心疾首啊!没加优化。。。
正解是对答案进行二分,每个统计用dp与二进制枚举
(跳石头,做过没?)
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<limits.h>using namespace std;struct dirt{int e,c;}a[105];int h[105];int n,m,k,t1,t2,t3;int ans;void dfs(int tot,int i){//搜索,没有任何优化,如果考虑优化的话也许就不是这个结果了 //printf("%d %d\n",tot,i);if(i>n){if(tot<=m){int cmax=INT_MAX;for(int j=1;j<=n;j++)cmax=min(cmax,h[j]);ans=max(ans,cmax);}return;}int ne=a[i].e;int nc=a[i].c;if(nc+tot<=m){int lm=min(n,i+k-1);for(int j=i;j<=lm;j++){h[j]+=ne;}dfs(nc+tot,i+1);for(int j=i;j<=lm;j++){h[j]-=ne;}}dfs(tot,i+1);}int dp[105][2055];int Min(int xxx,int yyy){if(xxx==-1)return yyy;if(yyy==-1)return xxx;return min(xxx,yyy);}//注意重写这个min,因为是最小的,但-1的时候时不可以到达的。//所以说-1尽管比他们小,都得直接返回另外一个!!! //否则你的程序会无限0!!!! bool can(int limit){memset(dp,-1,sizeof(dp));dp[0][0]=0;for (int i=0;i<n;i++)for (int j=0;j<(1<<k);j++)//只要前K个,因为只有前K个的放置情况可以对其造成影响 //二进制枚举 if (dp[i][j]!=-1){int sum=0;for (int t=k-1;t>0;t--){if ((1<<t)&j)sum+=a[i-(k-1-t)].e;//扫位 枚举 }if (sum+h[i+1]>=limit)dp[i+1][j>>1]=Min(dp[i+1][j>>1],dp[i][j]);if (sum+h[i+1]+a[i+1].e>=limit)dp[i+1][(j>>1)|(1<<(k-1))]=Min(dp[i+1][(j>>1)|(1<<(k-1))],dp[i][j]+a[i+1].c);
//这是DP的过程}for (int j=0;j<(1<<k);j++)if (dp[n][j]!=-1)if (dp[n][j]<=m) return 1;return 0;}int l,r;int main(){//freopen("cover.in","r",stdin);//freopen("cover.out","w",stdout);scanf("%d %d %d",&n,&m,&k);for(int i=1;i<=n;i++){scanf("%d %d %d",&h[i],&a[i].e,&a[i].c);}if(n<=20){//如果范围小的话就搜索一下,其实大数据也就20多毫秒的TLE,哭死 dfs(0,1);cout<<ans<<endl;return 0;} else { //否则二分! l=0,r=100000000; while(l+1<r) { int mid=(l+r)>>1; if(can(mid)) l=mid; else r=mid-1;}//注意别出不来了到时候 }if(can(l+1))l++;//跳出的时候r==l+1//我们当然希望要更大的,所以试下l+ 1 cout<<l<<endl;return 0;}
1 0
- TYZ 8/23 道路覆盖
- TYZ 8/23 物语
- TYZ 8/23 原根
- TYZ 8/25 送分题
- TYZ 8/22 人品问题
- TYZ群赛 8/21解题报告
- TYZ 8/25 LJM 交换!交换!
- TYZ 8/25 ranwen的烦恼
- 道路覆盖--解题报告
- TYZ 8/22 艰难的抉择(非常男女)
- 道路覆盖 (二分答案+状压DP)
- TYZ 9/13 MAZE2
- jzoj. 3521. 【NOIP2013模拟11.7B组】道路覆盖(cover)
- 【NOIP2013模拟11.7B组】道路覆盖(cover)
- JZOI 3521 道路覆盖 二分答案+状压dp
- 道路
- 道路
- 道路
- 自定义控件--快速检索
- 记一次存储过程学习及存其常用函数
- Permutations
- C#获取网页内容的三种方式
- NoSQL数据库----MongDB数据库
- TYZ 8/23 道路覆盖
- 水晶字体——老九门(做的有些失败,以后还要多练)
- 关于JDBC的ResultSet.TYPE_SCROLL_SENSITIVE无效的问题解析
- 内部类和匿名内部类
- Oracle Linux 7修改启动默认项
- mysql存储过程(转载详解)已备自己将来查看
- KMP算法
- 单例模式
- java nio 学习之 Buffer 类