QBXT2018 4 29 DP&图论班 胡策 by zhx
Posted dprswdr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QBXT2018 4 29 DP&图论班 胡策 by zhx相关的知识,希望对你有一定的参考价值。
PS:由于长者是以我们没有学过图论与DP的基础上出的题,所以可能(?)会有点水。
题意:
T1:判断括号序列是是否合法。可以利用栈,别忘了判断最终栈是否为空。
#include<cstdio> #include<cstdlib> #include<cstring> using namespace std; char s[1000],z[1000]; int size; int main() { scanf("%s",s+1); int l=strlen(s+1); size++; z[size]=s[1]; for (int a=2;a<=l;a++) { if (s[a]==\')\') { if (z[size]!=\'(\') { printf("Wrong\\n"); return 0; } else size--; } if (s[a]==\']\') { if (z[size]!=\'[\') { printf("Wrong\\n"); return 0; } else size--; } if (s[a]==\'}\') { if (z[size]!=\'{\') { printf("Wrong\\n"); return 0; } else size--; } if (s[a]==\'(\' || s[a]==\'[\' || s[a]==\'{\') { size++; z[size]=s[a]; } } if (size!=0) printf("Wrong\\n"); else printf("OK\\n"); return 0; }
T2:0/1/2背包 可以将物品复制一份跑0/1背包板子,也可以变化转移方程
f[i][j]=max{f[i-1][j],f[i-1][j-w[i]]+v[i],f[i-1][j-2*w[i]]+2*v[i]}
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int maxn=210; int n,m,w[maxn],v[maxn],f[maxn][maxn]; int main() { scanf("%d%d",&n,&m); for (int a=1;a<=n;a++) scanf("%d%d",&w[a],&v[a]); for (int a=0;a<n;a++) for (int b=0;b<=m;b++) { f[a+1][b]=max(f[a+1][b],f[a][b]); if (b+w[a+1]<=m) f[a+1][b+w[a+1]]=max(f[a+1][b+w[a+1]],f[a][b]+v[a+1]); if (b+2*w[a+1]<=m) f[a+1][b+2*w[a+1]]=max(f[a+1][b+2*w[a+1]],f[a][b]+2*v[a+1]); } int ans=0; for (int a=0;a<=m;a++) ans=max(ans,f[n][a]); printf("%d\\n",ans); return 0; }
T3:超神贪心
钟长者说:”这道题放在第二题下面,就是让你们把它当成背包做的。“。。。然后全场只有一位同学拿了10分,不愧为防AK好题 PS:好像这题一星期前还是最长上升子序列。。
此题具有特殊性质:每件物品都是1x2或1x3的,因此我们所选的物品就像俄罗斯方块一样放在一起。
SO此题可以抽象为选a个1x2的物品,b个1x3的物品。而我们可以贪心地将物品按价值从大到小拿取。
这里我们可以前缀和优化,预处理出前i件物品的价值和。其中s2[]代表1x2的价值前缀和,s3[]代表1x3的价值前缀和。
①枚举a,b 则答案ans为max{ans,s2[a]+s3[b]};
②可以只枚举b 然后根据b算出a
贪心地想,我们需要将剩余的空间尽可能用1x2的方格填满,因此所选择的1x2的方格的数量为a=min{n1,a=(n*m-3*b)/2}//n1为已知的1x2方格的数量 ,’/‘为整除(下取整)
证明:当我们填完枚举的1x3的方格时,会留下两个矩形。↓
当矩形1宽度为0时,a的数目取决于矩形2面积的奇偶性 即a=(n*m-3*b)/2
当矩形1宽度为1时,我们可以先用2格方格填充矩形2 而矩形2最多会被留出一个1x1个空间 然后再竖着用2格方格填满矩形1 因此a的数目也为(n*m-3*b)/2
当矩形1宽度为2时,我们可以用2格方格填满矩形1 而a的数目取决于矩形2面积的奇偶性 即a=(n*m-3*b)/2
③那么b的范围是什么呢?是min(n2,n*m/3) 吗?//n2为已知的1x3方格的数量
有特殊情况:当空间为1x2、2x1、2x2时,不能放1x3的方格,因此这些情况应当特判。
有同学可能会问,若矩形2形成了2x2的方格会有影响吗?比如5x5
我们可以这么摆
也可以这么摆
因此只需特判2x2、1x2、2x1的情况即可。
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int maxn=10010; int n,m,n1,n2,y[maxn],z[maxn],sum[maxn]; bool cmp(int a,int b) { return a>b; } int main() { int t; scanf("%d",&t); for (;t--;) { scanf("%d%d%d%d",&n,&m,&n1,&n2); for (int a=1;a<=n1;a++) scanf("%d",&y[a]); for (int a=1;a<=n2;a++) scanf("%d",&z[a]); sort(y+1,y+n1+1,cmp); sort(z+1,z+n2+1,cmp); for (int a=1;a<=n1;a++) y[a]+=y[a-1]; for (int a=1;a<=n2;a++) z[a]+=z[a-1]; int delta; if (n%3==2 && m%3==2 && (n==2 || m==2)) delta=4; else delta=n*m%3; int ans=0,limit=min(n2,(n*m-delta)/3); for (int a=0;a<=limit;a++) ans=max(ans,z[a]+y[min(n1,(n*m-a*3)>>1)]); printf("%d\\n",ans); } return 0; }
T4:
考场上想出了正解,然而又想了个数据,是”不是最短路上的一条边连着一个速度很大的马“。然后就写了个BFS,拿了40。。。。
已知有Q次询问,每次询问从u到v的最短时间,再根据数据范围,可以判断此题需要用到Floyd。
易证相同速度时路程越短时间越少,因此可以先预处理出任意两点间的最短路。
然后判断有哪些最短路是可以不换马走完的,此时该路径的时间即为“路径长度/路径起点的马的速度“。
根据这些已经得到的时间,我们可以进一步得到需要换马的路所需的时间,从而得到任意两点间的最短时间。
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int maxn=110; int n,q,e[maxn],s[maxn]; double dis[maxn][maxn],dist[maxn][maxn]; int main() { int T=1; for (int t=1;t<=T;t++) { scanf("%d%d",&n,&q); for (int a=1;a<=n;a++) scanf("%d%d",&e[a],&s[a]); for (int a=1;a<=n;a++) for (int b=1;b<=n;b++) { scanf("%lf",&dis[a][b]); if (dis[a][b]<0) dis[a][b]=1e+20; if (a==b) dis[a][b]=0; } for (int a=1;a<=n;a++) for (int b=1;b<=n;b++) for (int c=1;c<=n;c++) dis[b][c]=min(dis[b][c],dis[b][a]+dis[a][c]); for (int a=1;a<=n;a++) for (int b=1;b<=n;b++) dist[a][b]=1e+20; for (int a=1;a<=n;a++) dist[a][a]=0; for (int a=1;a<=n;a++) for (int b=1;b<=n;b++) if (dis[a][b]<=e[a]) dist[a][b]=dis[a][b]/s[a]; for (int a=1;a<=n;a++) for (int b=1;b<=n;b++) for (int c=1;c<=n;c++) dist[b][c]=min(dist[b][c],dist[b][a]+dist[a][c]); //printf("Case #%d:",t); for (int a=1;a<=q;a++) { int s,e; scanf("%d%d",&s,&e); printf("%.6lf\\n",dist[s][e]); } } return 0; }
以上是关于QBXT2018 4 29 DP&图论班 胡策 by zhx的主要内容,如果未能解决你的问题,请参考以下文章