jzoj 2017.8.7 B

xiaoxiao2021-02-28  103

第一题

天平 (Standard IO) Time Limits: 1000 ms Memory Limits: 65536 KB Detailed Limits

Description

FJ有一架用来称牛的体重的天平。与之配套的是N(1<=N<=40)个已知质量的砝码(所有砝码质量的数值都在31位二进制内)。每次称牛时,他都把某头奶牛安置在天平的某一边,然后往天平另一边加砝码,直到天平平衡,于是此时砝码的总质量就是牛的质量(FJ不能把砝码放到奶牛的那边,因为奶牛不喜欢称体重,每当FJ把砝码放到她的蹄子底下,她就会尝试把砝码踢到FJ脸上)。天平能承受的物体的质量不是无限的,当天平某一边物体的质量大于C(1<=C<2^30)时,天平就会被损坏。 砝码按照它们质量的大小被排成一行。并且,这一行中从第3个砝码开始,每个砝码的质量至少等于前面两个砝码(也就是质量比它小的砝码中质量最大的两个)的质量的和。 FJ想知道,用他所拥有的这些砝码以及这架天平,能称出的质量最大是多少。由于天平的最大承重能力为C,他不能把所有砝码都放到天平上。 现在FJ告诉你每个砝码的质量,以及天平能承受的最大质量。你的任务是选出一些砝码,使它们的质量和在不压坏天平的前提下是所有组合中最大的。

Input

第1行: 两个用空格隔开的正整数,N和C。 第2..N+1行: 每一行仅包含一个正整数,即某个砝码的质量。保证这些砝码的质量是一个不下降序列。

Output

第1行: 一个正整数,表示用所给的砝码能称出的不压坏天平的最大质量。

Sample Input

3 15 1 10 20

Sample Output

11

Hint 【样例说明】 FJ有3个砝码,质量分别为1,10,20个单位。他的天平最多只能承受质量为15个单位的物体。用质量为1和10的两个砝码可以称出质量为11的牛。这3个砝码所能组成的其他的质量不是比11小就是会压坏天平。

题解:由于各种原因这题打个dfs就可以AC,但纯dfs只能拿60分,所以我们要用一点小技巧,那就是剪枝。具体代码见。

#include<iostream> #include<cstdio> using namespace std; long long n,nn,c,a[50],summ[50]; long long ans=0; void dfs(long long n,long long sum) { if(sum+summ[n]<=ans) return ;//重点,剪枝操作,可以助你从60分变为100分 if(ans<sum) ans=sum;//更新ans的值 for(int i=n;i;i--) { if(sum+a[i]<=c) { dfs(i-1,sum+a[i]); } } } int main() { cin>>n>>c; nn=n; int r=0; for(int i=1;i<=nn;i++) { scanf("%lld",&a[i]); if(a[i]>c&&r==0)//如果第i个数大于c,那么我们要求的有效数字就是从1到当前的i-1个数 { n=i-1; r=1; } if(a[i]<=c) summ[i]=summ[i-1]+a[i];//求前缀和 } dfs(n,0); cout<<ans; return 0; }

第二题

游历的路线(lines.pas/cpp) (File IO): input:lines.in output:lines.out Time Limits: 1000 ms Memory Limits: 131072 KB Detailed Limits

Description

   我们的郭嘉大大经过一段时间发现了袁绍这个人干大事而惜身,见小利而忘义,又逢曹操在招兵买马,决定逃离袁绍去投曹操,而我们的曹操在第M天招募良材,我们的郭嘉大大既不能早去,也不能晚去,于是乎,他就趁着这一段时间到其他的城市游历一番,而每两个城市之间只能坐马车来往,由于我们的郭嘉大大很贪钱,他想用最少的费用,所以需要我们帮他求出这一个最小的费用。

Input

  第一行包含两个数n,m, 表示有n个城市,和m天后曹操招纳良材。城市一就是郭嘉所在的城市,城市n就是曹操处。接下来n * (n – 1)行描述马车乘坐表。   第2到第n行就是描述的城市1到2… n的马车乘坐表.   第n + 1到第2n-1行描述的城市2到城市1,3..n的马车乘坐表… … 对每一行,首先有一个数T,表示城市I到城市J的马车以T为周期,接下来有T个数,表示每天的马车的价格,如果价格为0则表示没有马车可坐。(n <= 100, m <= 200, T <= 20, Price <= 50000)

Output

  如果存在这样的路线使郭嘉第m天到达曹操处,则输出最少的费用,否则输出0!

Sample Input

3 5 2 130 150 3 75 0 80 2 110 100 4 60 70 60 50 3 0 135 140 2 70 80

Sample Output

355

题解: 题目大意:有m-1次坐车的机会,要使最后到n市,从一个市出发到其他市的马车都有一个周期,周期不同费用不一样。现在要求满足情况的最小费用 我们可以想到用dp解决此题,方程式也是很好推,设f[k][i]为第k天到i城市的最小花费, 然后输入时用一个a[k][i][j]保存周期内的第几天从i城市走到j城市的花费。

#include<iostream> #include<cstring> #include<cstdio> using namespace std; long long int n,m,a[21][101][101],f[201][101],t,ans=0,next,maxt=-1; int wei(int k,int i) { if(k%i==0) return i; else return k%i; } int main() { //freopen("lines.in","r",stdin); //freopen("lines.out","w",stdout); memset(a,0,sizeof(a)); memset(f,0x7f,sizeof(f)); cin>>n>>m; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(j!=i) { scanf("%lld",&t); //cin>>t; a[0][i][j]=t; for(int k=1;k<=t;k++) { scanf("%lld",&a[k][i][j]); //cin>>a[k][i][j]; if(a[k][i][j]==0) a[k][i][j]=0x7fffffff;//如果为0,就赋值一个超大值 } } } } f[0][1]=0;//初始化 for(int k=1;k<=m;k++) { for(int j=1;j<=n;j++) { for(int i=1;i<=n;i++) { if(i!=j) { int kk=wei(k,a[0][i][j]); f[k][j]=min(f[k-1][i]+a[kk][i][j],f[k][j]);//转移方程 } } } } cout<<f[m][n]; return 0; }

第三题

最短路(shortest) Time Limits: 3000 ms Memory Limits: 262144 KB Detailed Limits

Description

小Y最近学得了最短路算法,一直想找个机会好好练习一下。话虽这么说,OJ上最短路的题目都被他刷光了。正巧他的好朋友小A正在研究一类奇怪的图,他也想凑上去求下它的最短路。 小A研究的图可以这么看:在一个二维平面上有任意点(x,y)(0<=x<=N,0<=y<=M,且x,y均为整数),且(x,y)向(x-1,y)(必须满足1<=x)和(x,y-1)(必须满足1<=y)连一条边权为0的双向边。 每个点都有一个非负点权,不妨设(x,y)的权值为F[x][y],则有: 1.x=0或y=0:F[x][y]=1;2.其他情况:F[x][y]=F[x-1][y]+F[x][y-1]。 现在,小Y想知道(0,0)到(N,M)的最短路,即使得经过的点的权值之和最小。为了炫耀自己学过最短路算法,他决定和你进行一场比赛,看谁的程序跑得快。然则小Y没有学过高精度算法,所以他希望输出答案时只输出答案模1000000007后的值。

Input

一行两个正整数N,M,表示图的大小。

Output

一行一个整数Ans,表示答案模1000000007后的值。

Sample Input

1 2

Sample Output

6

Data Constraint

见图。

Hint

10%的数据满足N,M<=20;

30%的数据满足N,M<=100;

60%的数据满足min(N,M)<=100;

100%的数据满足N*M<=10^12。

题解: 【最短路】 这个图就是个划分后的矩形,也就是网格图。 20分看这里:暴力求出每个点权,然后使用DP或最短路算法。总效率O(NM)或O(NMLog(NM))。答案的范围在Int64/long long范围内。 60分看这里:暴力求出每个点权,然后使用DP或最短路算法。使用高精度储存答案。总效率O(NMA)或O(NMALog(NM))。其中A为答案长度。 观察原图,将x+y值相同的点(x,y)归为一层,将层按x+y值从小到大看,会发现其实整个图是杨辉三角的一部分。 容易看出,每层权值最小的点或都在最左侧或都在最右侧。由于N,M互换并不影响答案,所以假如每层权值最小的点都在最右侧,则交换N,M,保证每层权值最小的点都在最左侧。 从本质上说,就是该图的最短路是确定的,都是沿着矩形外围一圈走,且一开始先走矩形长的一边。 保证N<=M,那么答案可以直接算出,也就是M+C[M][0]+C[M+1][1]+…+C[M+N][N]。 120分看这里:用一个矩阵维护C[K][0]-C[K][N]的值。通过快速幂可以迅速得出C[M][0]-C[M][N]的值,由于答案涉及的排列数只有N+1项,所以接着逐级递推即可。总效率O(N^3LogM)。 200分看这里:把后面的排列数分别拆解开看: C[M][0]=1; C[M+1][1]=(M+1)/1; C[M+2][2]=(M+1)(M+2)/(1*2)=C[M+1][1]((M+2)/2); C[M+3][3]=C[M+2][2]*((M+3)/3); … C[M+N][N]=C[M+N-1][N-1]*((M+N)/N)。 由于模的数是一个素数,所以除以数a直接转化成乘数a的逆元。接着直接递推即可。总效率O(NLogN)。

转载请注明原文地址: https://www.6miu.com/read-68552.html

最新回复(0)