动态规划测试test20170430
来源:互联网 发布:乐高ev3编程软件安卓版 编辑:程序博客网 时间:2024/05/19 12:23
前言
这次考试据说有点难度,果然有些题目的确看着有些头晕,不过整体而言还算好吧。
题目
1.我不想写背景(wtf.pas/c/cpp)
【题目描述】
某巨魔去滑雪(没滑雪板),但他的技术并不精湛,在滑雪场里,每天会提供S门滑雪课。第i节课始于时间Mi,上课的时长为Li(只有在Mi时刻才能选择去上第i节课,其他时间不能选择上第i节课)。上完第i节课后,巨魔的滑雪能力会变成Ai. (注意:这个能力是绝对的,不是能力的增长值)。 巨魔买了一张地图,地图上显示了N个可供滑雪的斜坡,从第i个斜坡的顶端滑至底部所需的时长Di,以及每个斜坡所需要的滑雪能力Ci,以保证滑雪的安全性。巨魔的能力必须大于等于这个等级,以使得他能够安全滑下。 巨魔可以用他的时间来滑雪,上课,或者在旁边菊花丛中练习箭法,但是他必须在T时刻离开滑雪场。这意味着他必须在T时刻之前(或者T时刻)完成最后一次滑雪(或者上课)。 求巨魔在时间内最多可以完成多少次滑雪。这一天开始的时候,他的滑雪能力为1。
【输入格式】
第一行3个数字,T、S、N。
接下来S行,每行3个数字Mi、Li、Ai。
接下来N行,每行2个数字Ci、Di。
【输出格式】
一个整数,表示巨魔滑雪的最大次数。
【样例输入输出】
wtf.in
10 1 2
3 2 5
4 1
1 3
wtf.out
6
【样例解释】
0时刻,选择在第1个斜坡上滑雪,时间花费3。
3时刻,选择上第1节课。滑雪技术提高到5,时间花费2。
5时刻,选择在第2个斜坡上滑雪,时间花费1。
6时刻,选择在第2个斜坡上滑雪,时间花费1。
7时刻,选择在第2个斜坡上滑雪,时间花费1。
8时刻,选择在第2个斜坡上滑雪,时间花费1。
9时刻,选择在第2个斜坡上滑雪,时间花费1。
10时刻,收队了。
总滑雪次数:6
【数据范围】
50%的数据:
100%的数据:
【题解】
原题在此:P2948 [USACO09OPEN]滑雪课Ski Lessons
我们可以直接令
然后发现还是会超时,所以就要进行优化操作,我们可以发现提前把第i个培训记录到
所以我们可以得到
然后就不会超时了。
【代码】
#include <cstdio>#include <cstring>#include <algorithm>#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))inline int read() { int in=0,f=1; char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1; for(;ch>='0'&&ch<='9';ch=getchar ()) in=in*10+ch-'0'; return in*f;}const int maxn = 10000+10;const int maxs = 100+10;struct Cr { int x,y,lv;}cource[maxs];struct Node { int lv,w;}node[maxn];int t,n,s,Lv;int f[maxn],w[maxn],lv[maxn];int ff[maxs][maxn];int rec[maxs][2];namespace myself { bool cmp(const Node &a,const Node &b) { return a.lv<b.lv; } bool cmp2(const Cr &a,const Cr &b) { return a.x<b.x; } inline void pre() { std::sort(node+1,node+n+1,cmp); rec[node[1].lv][0]=1; for(int i=1;i<=n;i++) { while(node[i].lv==node[i+1].lv) { i++; } rec[node[i].lv][1]=i;rec[node[i+1].lv][0]=i+1; } } inline void work1() { for(int k=1;k<=Lv;k++) { if(rec[k][0]!=rec[k][1] or rec[k][0]) { for(int i=rec[k][0];i<=rec[k][1];i++) for(int j=node[i].w;j<=t;j++) f[j]=Max(f[j],f[j-node[i].w]+1); } for(int i=1;i<=t;i++) ff[k][i]=f[i]; } } inline void work2() { work1(); memset(f,0,sizeof f); std::sort(cource+1,cource+s+1,cmp2); cource[s+1].x=t;cource[0].y=0;cource[0].lv=1; for(int i=s;i>=0;i--) { for(int j=i+1;j<=s+1;j++) { if(cource[j].x-cource[i].x-cource[i].y>=0) f[i]=Max(f[i],f[j]+ff[cource[i].lv][cource[j].x-cource[i].x-cource[i].y]); } } printf("%d\n",f[0]); }}int main() { freopen("wtf.in","r",stdin); freopen("wtf.out","w",stdout); t=read();s=read();n=read(); for(int i=1;i<=s;i++) { cource[i].x=read();cource[i].y=read(); cource[i].lv=read();Lv=Max(Lv,cource[i].lv); } for(int i=1;i<=n;i++) { node[i].lv=read();node[i].w=read(); } myself::pre(); myself::work2(); return 0;}
2.我真不想写背景(wth.pas/c/cpp)
【题目描述】
某巨魔突然对等式很感兴趣,他正在研究 a1x1+a2x2+…+anxn=B 存在非负整
数解的条件,他要求你编写一个程序,给定 N、{an}、以及 B 的取值范围,求出
有多少 B 可以使等式存在非负整数解。
【输入格式】
输入的第一行包含 3 个正整数,分别表示 N、BMin、BMax 分别表示数列的
长度、B 的下界、B 的上界。
输入的第二行包含 N 个整数,即数列{an}的值。
【输出格式】
输出一个整数,表示有多少 B 可以使等式存在非负整数解。
【样例输入输出】
wth.in
2 5 10
3 5
wth.out
5
【样例解释】
对于 B=5,式子有 x1=0,x2=1。
对于 B=6,式子有 x1=2,x2=0。
对于 B=7,无解。
对于 B=8,式子有 x1=1,x2=1。
对于 B=9,式子有 x1=3,x2=0。
对于 B=10,式子有 x1=0,x2=2。
【数据范围】
20%的数据,
40%的数据,
100%的数据,
【题解】
原题:bzoj2118 墨墨的等式
40分:
由于b的数量较小,这就和我们平时使用的动态规划算法没有什么区别,这就是的完全背包问题,动态规划方程:
100分:
找一个ai,若x为合法的B,则x+ai也合法
设bi为最小的x,满足x mod mn = i
求出每个bi就可以求答案了
bi用最短路求就好了啊 意会一下
最后枚举余数搞一下就算出答案了
详细一点的解释可以看LCY大神的blog
【代码】
#include<bits/stdc++.h>using namespace std;typedef long long LL;const int N=500002;inline LL read(){ char ch=getchar(); LL x=0; while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();} return x;}struct g{ LL w;int x; bool operator <(g a)const{return w>a.w;}};struct u{int y;LL c;int next;}a[12*N]; int len,first[N];void ins(int x,int y,LL c){a[++len]=(u){y,c,first[x]},first[x]=len;}int o[13]; LL d[N];priority_queue<g>q;int main(){ int n=read(),i,j,mn=1e6; LL b1=read(),b2=read(); for(i=1;i<=n;i++)o[i]=read(),mn=o[i]<mn?o[i]:mn; for(i=1;i<mn;i++)d[i]=1e15; for(i=1;i<=n;i++) if(o[i]%mn){ int _=o[i]%mn; for(j=0;j<mn;j++)ins(j,(j+_)%mn,o[i]); } q.push((g){0,0}); while(!q.empty()){ g r=q.top(); q.pop(); int x=r.x; if(r.w!=d[x])continue; for(int k=first[x];k;k=a[k].next){ int y=a[k].y; if(d[y]>d[x]+a[k].c)q.push((g){d[y]=d[x]+a[k].c,y}); } } LL ans=0; for(i=0;i<mn;i++)if(d[i]<=b2){ LL l=max(0ll,(b1-d[i])/mn); if(l*mn+d[i]<b1)l++; LL r=(b2-d[i])/mn; ans+=r-l+1; } printf("%lld\n",ans); return 0;}
3.我真不想写背景
【题目描述】
某巨魔有一风扇,长得和下图一个怂样。这风扇原来有 N 个等分叶片,顺时针编号 1到 N(谁是编号 1 这不重要)。任意两个相邻的叶片间隔相等,大小质地相同。这个 N 满足
【输入格式】
第一行两个数字 N,M,表示该风扇原来有 N 个叶片现在已经脱落了 M 个叶片。
接下来 M 行,每行一个数字,表示脱落的叶片编号,按升序给出。
【输出格式】
一个数字,表示为使电风扇平衡所需要拆掉的叶片的最少数量。
【样例输入输出】
damn.in
12 5
1
4
5
9
10
damn.out
0
【样例解释】
拆完后就是上图那怂电风扇。
【数据范围】
30%的数据:
50%的数据:
100%的数据:
【题解】
然而这个题目其实要用网络流,本人并不会,还是放弃。
【代码】
#include <cstdio>int main() { freopen("damn.in","r",stdin); freopen("damn.out","w",stdout); puts("0");//10分 return 0;}
总结
这次考试其实第二题没有往图论方面去想,导致了完全背包走人的结果,不过似乎大家都没想出来。。。
- 动态规划测试test20170430
- 动态规划测试test20170506
- 动态规划测试test20170511
- 动态规划测试test20170520
- 动态规划测试test20170513
- 动态规划测试test20170525
- 动态规划测试test20170518
- 动态规划测试3(test20170406)
- 【DP】TEST20170430
- 动态规划!!!动态规划!!!
- 卷积和动态规划的简单测试程序
- 5月6日动态规划测试解题报告
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- HDU1372 Knight Moves(bfs)
- 将数值转化为字符
- TCP、UDP、IP 协议分析
- poj2386
- 实训6/6 Python 模块
- 动态规划测试test20170430
- Android中通过Intent来传递对象
- C#:ComboBox中TextChanged事件不被触发的探究
- deepin/win10双系统deepin下其他盘带锁解决
- iOS XCode storyboard 设置控件三等分屏幕的约束添加
- android AlertDialog例子(恢复系统出厂设置)
- priority_queue practice
- 第一周编程作业--1求最大公约数和最小公倍数2排序并插入
- Linux系统手动升级gcc