【9.14NOIP模拟pj】wtaxi 题解——搜索
来源:互联网 发布:崩坏学园2淘宝代练 编辑:程序博客网 时间:2024/05/23 19:25
【9.14NOIP模拟pj】wtaxi
题目简化
有K辆车,N个人,上车给D元,只有S分钟。上车后无论多少人都要给D元,原地等多少分钟就没了多少元。求最小花费的钱。
我的思路
毫无疑问,此题可以用搜索做,DFS和BFS都行。
程序1
设三个参数,分别为(第l辆车,共花了sum元,还剩下m人)。花的时间在后面加上,否则有点麻烦一点。
两种情况:选或不选:
不选 l+1;
选 l+1,已经花的钱+时间*上车人数+上车需要的钱(D),m-上车的人
程序2
我觉得,纯暴搜定然不过,所以加个记忆化。因为记忆化必须要在后面的操作一样时,才可以比较,取最优的。设bz[l,m]表示在第l辆车,剩m人时花的最少钱(sum)
和sum比较即可
程序3.1
我担心第二代程序过不了,再加了一层优化。有时,剩下的人即使将剩下的车全坐满,仍然不够。所以判断m和剩下的座位之和的关系,若m比其还大,则退出,因为即使后面的坐满,仍不能全走。
(未试过)程序3.2
已经满的车无需考虑
所以,此题可用**DFS+记忆化+剪枝**AC之
程序实践3.1
C++
#include <cstdio>#include <cstring>#include <cmath>#include <climits>using namespace std;int n,k,d,s; int t[101],z[101]; int bz[101][101],sm[102];//bz见上,sm[i]表示到i辆车时剩下的车最多能坐的人数(包括i)int ans=INT_MAX;int min_a_b(int a,int b){ if (a<b) return a; return b;}void go(int l,int sum,int m){ if (sum>bz[l][m]) return; bz[l][m]=sum;//记忆化操作,把大于之前的排除 if (sm[l]<m) return;//剪枝操作,把大于最大座位的人数排除 if (m<=0) { if (sum<ans) ans=sum;//替换ans return; } if (l>k) return;//车没了,人还在的情况 go(l+1,sum+min_a_b(z[l],m)*t[l]+d,m-min_a_b(z[l],m));//选 go(l+1,sum,m);//不选 return;}int main(){ freopen("wtaxi.in","r",stdin); freopen("wtaxi.out","w",stdout); int i,j; scanf("%d%d%d%d",&n,&k,&d,&s); for(i=1;i<=k;i++) { scanf("%d%d",&t[i],&z[i]); } for(sm[k+1]=0,i=k;i>0;i--) { sm[i]=sm[i+1]+z[i];//求剩下车中最大座位 } memset(bz,127,sizeof(bz));//初始化 go(1,0,n); if (ans==INT_MAX) { printf("impossible\n"); return 0; } printf("%d\n",ans); return 0;}
Pascal
var n,k,d,s:longint; i,j:longint; t,z:array[0..100]of longint; bz:array[0..100,0..100]of longint;//bz见上 sm:array[0..101]of longint;//sm[i]表示到i辆车时剩下的车最多能坐的人数(包括i) ans:longint=maxlongint;function min(a,b:longint):longint;begin if a<b then exit(a); exit(b);end;procedure go(l,sum,m:longint);begin if sum>bz[l,m] then exit; bz[l,m]:=sum;//记忆化操作,把大于之前的排除 if sm[l]<m then exit;//剪枝操作,把大于最大座位的人数排除 if m<=0 then begin if sum<ans then ans:=sum;//替换ans exit; end; if l>k then exit;//车没了,人还在的情况 go(l+1,sum+min(z[l],m)*t[l]+d,m-min(z[l],m));//选 go(l+1,sum,m);//不选end;begin assign(input,'wtaxi.in');reset(input); assign(output,'wtaxi.out');rewrite(output); readln(n,k,d,s); for i:=1 to k do readln(t[i],z[i]); sm[k+1]:=0; for i:=k downto 1 do sm[i]:=sm[i+1]+z[i];//求剩下车中最大座位 fillchar(bz,sizeof(bz),127);//初始化 go(1,0,n); if ans=maxlongint then begin writeln('impossible'); close(input); close(output); halt; end; writeln(ans); close(input); close(output);end.
总结
- 类似于这样的题可以用搜索做
- 记忆化可以加快程序速度,但要保证程序是正确的,只是删掉不必要的运算
1.不一定要保证前面走过的路一样
2.要保证后面的路一样,它们要在同一可以比较的点上,才能记忆化,取最优的 - 剪枝也可以删掉一些不必要的运算,但它是根据最不利原则,求出的一个范围,把范围外的去掉
0 0
- 【9.14NOIP模拟pj】wtaxi 题解——搜索
- 【9.14NOIP模拟pj】wtaxi 题解
- noip模拟题—跳跃版图 题解
- NOIP模拟21题解
- NOIP模拟题题解
- 2017.1.16【初中部 】普及组模拟赛C组 wtaxi 题解
- 2016NOIP PJ 总结
- NOIP-2016-PJ-总结
- NOIP PJ懵逼记
- NOIP 2017 PJ
- 【NOIP模拟】20140809 题解 & 总结
- 【NOIP模拟】20140812 题解 & 总结
- 【NOIP模拟】20140813 题解 & 总结
- 【NOIP模拟】20140814 题解 & 总结
- 【NOIP模拟】20140815 题解 & 总结
- 【NOIP模拟】20140817 题解 & 总结
- 【NOIP模拟】20140907 题解 & 总结
- 【NOIP模拟】20140913 题解 & 总结
- Android 中12时56分这类的处理
- Linux怎么改变文件权限(通过数字类型)
- 各种开源项目/库/工具介绍
- 回文字符串ACM问题
- 注释转换(c—>c++)
- 【9.14NOIP模拟pj】wtaxi 题解——搜索
- mysql主从复制踩坑一
- [BZOJ1023]静态仙人掌 Tarjan+dp+单调队列
- 1-16数论学习总结
- USACO 2.2 Subset Sums
- 第一个星期
- Codeforces Round #391 -A. Gotta Catch Em' All!
- Redis在window下的安装配置
- 四、安装cuDNN,caffe和openCV