10.10 高校模拟赛 贪心模拟+BFS+DP
来源:互联网 发布:云计算判断题 编辑:程序博客网 时间:2024/06/06 13:21
- 出题人
- Problem 1 painter
- 题目来源
- 题目描述
- 题解
- 代码
- Problem 2 escape
- 来源
- 题目描述
- 题解
- 代码
- Problem 3 balance
- 题目来源
- 题目描述
- 题解
- 代码
出题人
(排名不分先后):
Dewct http://loifrancis.gq/
zzk http://blog.csdn.net/loi__zzk
Cunese 大爷的csdn忘了,,行吧
whales http://blog.csdn.net/cherish_k
Problem 1 painter
题目来源:
http://poj.org/problem?id=2709
题目描述
杂货店出售一种由N(3<=N<=12)种不同颜色的颜料,每种一瓶(50ML),组成的颜料套装。你现在需要使用这N种颜料;不但如此,你还需要一定数量的灰色颜料。杂货店从来不出售灰色颜料——也就是它不属于这N种之一。幸运的是,灰色颜料是比较好配置的,如果你取出三种不同颜色的颜料各x ml,混合起来就可以得到xml的灰色颜料(注意不是3x)。
现在,你知道每种颜料各需要多少ml。你决定买尽可能少的“颜料套装”,来满足你需要的这N+1种颜料。那么你最少需要买多少个套装呢?
输入描述 输入包含若干组测试数据。每组数据一行:第一个数N, 3<=N<=12, 含义如上;接下来N+1个数,分别表示你需要的N+1种颜料的毫升数。最后一种是灰色。所有输入的毫升数<=1000.
注意:输入中不存在每个颜料套装的毫升数。由题意可知,每种各50ml,即一共50N ml
输出描述 每组数据输出一行,最少需要的套装数。
样例输入 3 40 95 21 0
7 25 60 400 250 0 60 0 500
4 90 95 75 95 10
5 0 0 0 0 0 333
0
样例输出 2
8
2
4
数据范围及提示 对于30%的数据 N=3
对于100%的数据3 <= N <= 100
数据最多不超过10组
题解:
先不考虑灰色,满足其他颜料至少需要ans;
每次操作,选取剩余颜料最多的三种,合成1单位灰色颜料,重新sort;
若不足三种且未合成足够的灰色,则ans++,每种颜料加50
代码:
直接sort的std#include<iostream>#include<cstdio>#include<algorithm>using namespace std;int maxx,ans,n,gry;int b[10000];void init(){ maxx=0; ans=0;}bool cmp(int a,int b){ return a>b;}int main(){ while(scanf("%d",&n)!=EOF){ if(n==0) return 0; init(); for(int i=1;i<=n;i++) scanf("%d",&b[i]),maxx=max(maxx,b[i]); scanf("%d",&gry); ans=maxx/50; if(maxx%50) ans++,maxx=ans*50; for(int i=1;i<=n;i++) b[i]=maxx-b[i]; sort(b+1,b+n+1,cmp); while(gry>0){ if(b[3]==0){ ans++; for(int i=1;i<=n;i++) b[i]+=50; } b[1]--,b[2]--,b[3]--,gry--; sort(b+1,b+n+1,cmp); } printf("%d\n",ans); }}
我的cpp在poj上WA。。。。。随机数据太良心
考场代码需要改正的是:
1.记录每种颜料标号是不必要的,因为颜料的种类是无意义的,我们只关心它们是否不同。
2.没有特判灰色等于0,在剩余颜料不满两种的情况下,ans会+1;
调了一下午啊!!!!!!
考场 堆#include<iostream>#include<cstdio>#include<algorithm>#include<queue>using namespace std;const int N=150;int maxx,n,ned[N],ml[N],gry,cnt,ans;struct node{ int id,num;}tmp[5];priority_queue<node> Q;bool operator <(node a,node b){ return a.num<b.num;}void done(){ ans=maxx/50; if(maxx%50) ans++,maxx=ans*50; for(int i=1;i<=n;i++){ if(maxx-ned[i]) Q.push((node){i,maxx-ned[i]}); } if(Q.size()<=2){ ans++; for(int i=1;i<=n;i++) ml[i]=50; while(!Q.empty()){ node u=Q.top(); Q.pop(); ml[u.id]+=u.num; } for(int i=1;i<=n;i++){ Q.push((node){i,ml[i]}); } } while(!Q.empty()){ for(int i=1;i<=3;i++){ tmp[i]=Q.top(); Q.pop(); } cnt+=1; if(cnt>=gry) return ; for(int i=1;i<=3;i++){ if(tmp[i].num-1) Q.push((node){tmp[i].id,tmp[i].num-1}); } if(Q.size()<=2){ ans++; for(int i=1;i<=n;i++) ml[i]=50; while(!Q.empty()){ node u=Q.top(); Q.pop(); ml[u.id]+=u.num; } for(int i=1;i<=n;i++){ Q.push((node){i,ml[i]}); } } } return ;}void init(){ while(!Q.empty()) Q.pop(); ans=0; maxx=0; cnt=0; for(int i=1;i<=3;i++) tmp[i].id=0,tmp[i].num=0;}int main(){ freopen("painter.in","r",stdin); freopen("painter.out","w",stdout); while(scanf("%d",&n)!=EOF){ if(n==0) return 0; init(); for(int i=1;i<=n;i++) { scanf("%d",&ned[i]); maxx=max(maxx,ned[i]); } scanf("%d",&gry); done(); printf("%d\n",ans); } return 0;}
改 √ 了的堆#include<iostream>#include<cstdio>#include<algorithm>#include<queue>using namespace std;const int N=150;int maxx,n,ned[N],ml[N],gry,cnt,ans,tot;int tmp[5];priority_queue<int> Q;void add(){ ans++; tot=0; for(int i=1;i<=n;i++) ml[i]=50; while(!Q.empty()){ int u=Q.top(); Q.pop(); ml[++tot]+=u; } for(int i=1;i<=n;i++){ Q.push(ml[i]); }}void done(){ ans=maxx/50; if(maxx%50) ans++,maxx=ans*50; if(gry==0) return ;//!!!!!!!!!! for(int i=1;i<=n;i++){ if(maxx-ned[i]>0) Q.push(maxx-ned[i]); } if(Q.size()<=2){ add(); } while(!Q.empty()){ for(int i=1;i<=3;i++){ tmp[i]=Q.top(); Q.pop(); } cnt+=1; if(cnt>=gry) return ; for(int i=1;i<=3;i++){ if(tmp[i]-1>0) Q.push(tmp[i]-1); } if(cnt<gry&&Q.size()<=2){ add(); } }}void init(){ while(!Q.empty()) Q.pop(); ans=0; maxx=0; cnt=0;}int main(){ while(scanf("%d",&n)!=EOF){ if(n==0) return 0; init(); for(int i=1;i<=n;i++) { scanf("%d",&ned[i]); maxx=max(maxx,ned[i]); } scanf("%d",&gry); done(); printf("%d\n",ans); } return 0;}
Problem 2 escape
来源:
http://hzwer.com/4598.html
题目描述
给出数字N(1<=N<=10000),X(1<=x<=1000),Y(1<=Y<=1000),代表有N个敌人分布一个X行Y列的矩阵上,矩形的行号从0到X-1,列号从0到Y-1再给出四个数字x1,y1,x2,y2,代表你要从点(x1,y1)移到(x2,y2)。在移动的过程中你当然希望离敌人的距离的最小值最大化,现在请求出这个值最大可以为多少,以及在这个前提下,你最少要走多少步才可以回到目标点。注意这里距离的定义为两点的曼哈顿距离,即某两个点的坐标分为(a,b),(c,d),那么它们的距离为|a-c|+|b-d|。
输入描述 第一行给出数字N,X,Y
第二行给出x1,y1,x2,y2
下面将有N行,给出N个敌人所在的坐标
输出描述 在一行内输出你离敌人的距离及在这个距离的限制下,你回到目标点最少要移动多少步。
样例输入 2 5 6
0 0 4 0
2 1
2 3
样例输出 2 14
数据范围及提示
30%: n=1
100%: 1<=n<=1000, 1<=x<=1000, 1<=y<=1000
题解:
预处理出每个点到它最近敌人的距离(把敌人坐标丢进队列里,做bfs),将整张图扫一遍。
二分答案,按照预处理出的距离,判断某点是否能走,bfs;
注意:
二分判断时,首先判断起点是否合法!!
考试的时候,没有预处理,每二分一次重新标记图,成功tle!
代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<queue>#include<cstring>using namespace std;struct node{ int x,y,step;};bool used[1005][1005];int dis[1005][1005]; queue<node> Q;int n,X,Y,x1,x2,y1,y2,ans,a,b;int dx[10]={0,1,0,-1,0},dy[10]={0,0,1,0,-1};bool can(int x,int y,int mid){ if(x>=0&&x<X&&y>=0&&y<Y&&!used[x][y]&&dis[x][y]>=mid) return true; return false;}void init(int mid){ memset(used,0,sizeof(used)); while(!Q.empty()) Q.pop(); ans=0;}bool check(int x){ init(x); Q.push((node){x1,y1,0}); used[x1][y1]=1; if(dis[x1][y1]<x) return false; while(!Q.empty()){ node u=Q.front(); if(u.x==x2&&u.y==y2){ ans=u.step; return true; } Q.pop(); for(int i=1;i<=4;i++){ int xx=u.x+dx[i],yy=u.y+dy[i]; if(can(xx,yy,x)){ used[xx][yy]=1; Q.push((node){xx,yy,u.step+1}); } } } return false;}void done(){ while(!Q.empty()){ node u=Q.front(); Q.pop(); for(int i=1;i<=4;i++){ int xx=u.x+dx[i],yy=u.y+dy[i]; if(xx>=0&&xx<X&&yy>=0&&yy<Y&&!used[xx][yy]){ dis[xx][yy]=u.step+1; used[xx][yy]=1; Q.push((node){xx,yy,u.step+1}); } } } return ;}int main(){ freopen("escape.in","r",stdin); freopen("escape.out","w",stdout); scanf("%d%d%d",&n,&X,&Y); scanf("%d%d%d%d",&x1,&y1,&x2,&y2); for(int i=1;i<=n;i++){ scanf("%d%d",&a,&b); Q.push((node){a,b,0}); dis[a][b]=0; used[a][b]=1; } done(); int l=-1,r=100000000+800; while(r-l>1){ int mid=r+l>>1; if(check(mid)) l=mid; else r=mid; } check(l); printf("%d %d\n",l,ans); return 0;}
Problem 3 balance
题目来源:
https://vjudge.net/problem/POJ-1837
题目描述
有一个天平,天平左右两边各有若干个钩子,总共有C个钩子,有G个钩码,求将钩码全部挂到钩子上使天平平衡的方法的总数。
输入描述 第一行两个数c, g分别代表钩子数和钩码数
第二行c个数,表示每个钩子距离天平中央的距离c[i],负数表示在左边,正数表示在右边
第三行g个数,表示每个钩码的重量w[i]
输出描述 输出总方案数
样例输入
2 4
-2 3
3 4 5 8
样例输出 2
数据范围及提示 30%: c<=9, g<=9
100%: c<=20, g<=20, -15<=c[i]<=15, w[i]<=25
题解:
一道精彩的初中物理题
设置状态dp[i][j]表示放了i个钩码,平衡度为j的方案数;
平衡度的定义为:右边-左边
由此可知:左边重 j<0,右边重 j>0,平衡 j=0
由数据范围可以推测出,平衡度的绝对值小于7500
为了避免负数作为下标,将平衡度均+7500
枚举钩码 枚举放在哪个位置 枚举此时的平衡度 转移
总结一下,本题主要难在设计状态。
代码:
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;int g[25],w[25],dp[25][15020];int n,m;int main(){ freopen("balance.in","r",stdin); freopen("balance.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&g[i]); for(int i=1;i<=m;i++) scanf("%d",&w[i]); dp[0][7500]=1; for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ for(int k=0;k<=15000;k++){ if(k-w[i]*g[j]>=0) dp[i][k]+=dp[i-1][k-w[i]*g[j]]; } } } printf("%d",dp[m][7500]); return 0;}
result 100+40+0;
T1由于数据水,成绩不准确;
- 10.10 高校模拟赛 贪心模拟+BFS+DP
- Loi 模拟赛 贪心+模拟+DP+数论
- Loi 模拟赛之压轴出场的互测终曲|(*_-) 模拟+模拟+贪心+bfs+图论+数论
- [NOIP模拟][审题][数据结构][bfs/dp]
- NOIP模拟题[贪心][DP][数论]
- 做(do) (贪心模拟 dp)
- jzoj3929【NOIP2014模拟11.6】创世纪(图论,bfs,贪心)
- [队内测试Day10.10]贪心+模拟+BFS
- dp模拟
- CUGBACM_Summer_Tranning3 2013长沙现场赛(二分+bfs模拟+DP+几何)
- [NOIP模拟][bfs][dp][CSD][表达式的计算]
- Codeforces Round #408 (Div. 2) 思维,模拟,DP, 多点BFS
- [模拟考试题][神题]Star Sky[状压DP][BFS][差分]
- 2017.10.10队内互测——高校模拟赛
- #bzoj2932#【重庆市NOIP模拟赛】旅行(贪心 DP是不可以的!)
- hiho 1271 舰队游戏 状压dp 贪心 模拟
- NOIP模拟题 2016.8.27 [贪心] [DP] [计数问题]
- NOIP模拟题 River Path Word[排序][贪心][DP]
- 笔试题1
- mysql 5.5 和5.7 安装的区别
- 多媒体教室运维现状分析及解决措施
- <Arm开发板>使开发板连上外网及tftp下载命令
- Linux 树莓派 kali ifconfig: command not found 问题解决
- 10.10 高校模拟赛 贪心模拟+BFS+DP
- SpringBoot常见问题(二)--不重启替换静态资源
- python thread pool websocket client 高并发websocket客户端测试代码
- Java 多线程编程
- 我的CSDN博客开张了
- java上传文件到文件夹判断文件夹是否存在,不存在则创建
- linux 防火墙设置、访问ip限制、iptables命令
- Android 图片选择到裁剪之步步深坑
- C语言提高-第5讲: 函数的参数(回文、素数)