周六日常训练,背包dp,树形dp,简单dp以及很多数学?
来源:互联网 发布:c语言幻数什么意思 编辑:程序博客网 时间:2024/05/21 10:08
队内周六日常训练,我迟到了半个小时,然后两个dalao开始疯狂过题,这比赛是很多场现场赛组合来的,大概都是铜牌、铁牌,少部分银牌题。 比较适合我们队伍的情况。
A
似乎是二分图匹配? 简单的? 熊神交了几发就过了。
B
题意很简单:给a , b 求x,y 满足 x+y = a 且 lcm(x,y) = b
高中数学题
哼! 不是常说
模拟只会猜题意,贪心只能过样例。图论只会套模板,数论只会gcd
这下好了,出gcd了,你看还不是不会!
从x,y下手。我们设 gcd(x,y) = c
所以 x = i*c , y = j*c (i,j互质)
于是有:
lcm(x,y) = c*i*j = b
ic + jc = a = c*(i+j)
因为 i j 互质 i*j 的因数只有i和j 和1 和自己
所以 gcd(i+j , i*j) = gcd(i,i*j) 或者gcd(j,i*j);
假设 gcd(i,i*j)=x(x!=1)
则有:
i=ax
i*j=bx => j=(a-b)x 且可知a>b 所以 j=cx ,所以gcd(i,j)!=1 ,与题设矛盾
所以 gcd(i+j , i*j) =1 所以 gcd ( a,b ) = c
所以 i + j = a/c 且 i*j = b/c
然后就是解二元一次方程组。。。所以只需解出最小的i即可
C
给一个x 可以分成任意段:x1+x2+x3….,必须满足:
1.任何两段都不相同
2.求x1*x2*x3最大值
算了,不强行分析了,数论不是gcd,超出我的能力范围了。
D
点分治,熊神补了,先不看了
E
盒子里面有k个黑球,1个红球,谁先取出红球谁就胜利,问先手会有优势吗?
一开始没想好,以为后手会有优势,sb了一下。
k=1 一黑一红 先手既无优势也无劣势,55k
k=2 两黑一红,先手取1/3赢 即使没取到 轮到后手时 也是55k ,所以先手有优势。
k=3 三黑一红
000X
先手: 1/4 赢 3/4取不到
后手: 必须建立在先手取不到的情况: P(赢)=3/4 * 1/3 =1/4
然后55k。 所以 先手既无优势也无劣势,55k
k=4 0000X 先手取完一个之后,情况和k=3相同,所以先手肯定有优势
往后推 同理
F
貌似是个挺简单的计算几何,拆成三角形计算就可以了。 s=a*b*sinx*1/2?
G
化成二进制,然后再换成八进制,4位->1位
H
题意:一条路上有n条河,每条河有起点和终点,河里面会 随机在任何位置出现一条船,并且船的速度恒等于V,但是方向向左向右是随机的,走路的速度=1,求从A 走到B 的期望时间。
对单独一条河,过河的期望= 当船在河中心 的t(v向左)+t(v向右),这个怎么证明呢,我只能说根据题目条件可得= =,然后我们把所有河长度加起来当成一条河就可以了。
I
下载东西,一大堆规则,其实下载的总量是固定的,总速度是固定的,除一下就是答案。
J
HDU 3236
有很多物品,每个物品有体积,价值,属性(有些必须买,有些不必须)
给两个背包(v1,v2),跑0-1背包, 以及可以免费选任何一个物品。
求最大价值。
首先我们把物品分为必须和非必须
然后跑两遍0-1 背包,根本不需要记录我们选择了哪些物品
但必须记录我们选择完必须品之后的状态 dp[i][j] 。
#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<queue>#include<stack>#include<string.h>#include<map>#include<set>using namespace std;template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}int dp[505][55][2];//dp[i][j]代表使用的容量是i和j的最大价值, 再开一维表示免费的机会即可struct node{ int v,w; bool operator <(const node &b)const{ return v>b.v; }};priority_queue<node>q;int main(){ int V1,V2,i,j,a,b,c,k,n,ans,cas,sum,pre,sign; cas=1; while(~scanf("%d%d%d",&V1,&V2,&n)&&(V1||V2||n)){ vector<node> G[2]; memset(dp,-1,sizeof(dp)); for(i=0;i<n;i++){ scanf("%d%d%d",&a,&b,&c); // 分别是 体积和价值,是否必须 G[c].push_back((node){a,b}); } sum=dp[0][0][0]=0; for(i=0;i<G[1].size();i++){ pre=sum; sum+=G[1][i].w; for(j=V1;j>=0;j--){ // 第一个背包和第二个背包都必须扫 for(k=V2;k>=0;k--){ if(dp[j][k][0]==pre) //如果没用免费机会时,最大价值=pre dp[j][k][1]=sum; //则用了免费会变成 这样 if(j>=G[1][i].v){ if(dp[j-G[1][i].v][k][1]==pre) dp[j][k][1]=sum; if(dp[j-G[1][i].v][k][0]==pre) dp[j][k][0]=sum; } if(k>=G[1][i].v){ if(dp[j][k-G[1][i].v][1]==pre) dp[j][k][1]=sum; if(dp[j][k-G[1][i].v][0]==pre) dp[j][k][0]=sum; } } } } sign=0; for(i=0;i<=V1;i++) for(j=0;j<=V2;j++) for(k=0;k<=1;k++){ if(dp[i][j][k]!=sum) //检测是否能把必需品装下,并且我们知道剩下的状态是怎样 dp[i][j][k]=-1; else sign=1; //我们保存了使用i,j空间装满所有必需品的状态 } if(!sign){ printf("Case %d: -1\n\n",cas++); continue; } // for(i=0;i<G[0].size();i++){ for(j=V1;j>=0;j--){ for(k=V2;k>=0;k--){ if(dp[j][k][0]!=-1) //要放在最前面,避免了重复装入 dp[j][k][1]=max(dp[j][k][1],dp[j][k][0]+G[0][i].w); // 必须满足!=-1 即:把必需品装完 if(j>=G[0][i].v){ if(dp[j-G[0][i].v][k][1]!=-1) dp[j][k][1]=max(dp[j][k][1],dp[j-G[0][i].v][k][1]+G[0][i].w); if(dp[j-G[0][i].v][k][0]!=-1) dp[j][k][0]=max(dp[j][k][0],dp[j-G[0][i].v][k][0]+G[0][i].w); } if(k>=G[0][i].v){ if(dp[j][k-G[0][i].v][1]!=-1) dp[j][k][1]=max(dp[j][k][1],dp[j][k-G[0][i].v][1]+G[0][i].w); if(dp[j][k-G[0][i].v][0]!=-1) dp[j][k][0]=max(dp[j][k][0],dp[j][k-G[0][i].v][0]+G[0][i].w); } } } } ans=0; for(i=0;i<=V1;i++) for(j=0;j<=V2;j++) for(k=0;k<=1;k++) ans=max(ans,dp[i][j][k]); printf("Case %d: %d\n\n",cas++,ans); } return 0;}
K
树形dp, 我觉得自己写的没错,但是hdu上就是只写输入都会Tle,根本不知道怎么回事,只能贴一下自己代码了
我的做法:
dfs 回溯,在记录深度,根据深度来选择符合条件的最大或最小值。
#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<queue>#include<stack>#include<string.h>#include<map>#include<set>using namespace std;#define ll __int64#define N 500002struct Edge{ int to,di; int next;};Edge edge[N*2];int head[N],tot;void addedge(int u,int v,int d){ edge[tot].to=v; edge[tot].di=d; edge[tot].next=head[u]; head[u]=tot++;}int dis[N],L,R;int deep[N],n;int ans[N];void dfs(int u,int pre){ int flag=0; for(int i=head[u];i!=-1;i=edge[i].next){ int to=edge[i].to; int l=edge[i].di; if(to==pre) continue; flag=1; deep[to]=deep[u]+1; if(dis[u]>R) dis[to]=R+1; else dis[to]=dis[u]+l; dfs(to,u); } if(!flag) //叶子 if(L<=dis[u] && dis[u]<=R) ans[u]=dis[u]; if(ans[u]!=-1){ if(ans[pre]==-1 ) ans[pre]=ans[u]; else{ if(deep[pre]&1) ans[pre]=max(ans[pre],ans[u]); else ans[pre]=min(ans[pre],ans[u]); } }}void init(int n){ memset(dis,0,sizeof(dis)); memset(ans,-1,sizeof(ans)); memset(head,-1,sizeof(head)); deep[0]=1; dis[0]=tot=0; //所以deep奇数选最大,偶数选最小}int main(){ //freopen("1.txt","r",stdin); while(~scanf("%d %d %d",&n,&L,&R)){ init(n); int a,b,c; for(int i=1;i<n;i++){ scanf("%d %d %d",&a,&b,&c); addedge(a,b,c); addedge(b,a,c); } dfs(0,0); if(ans[0]==-1) printf("Oh, my god!\n"); else printf("%d\n",ans[0]); } return 0;}
M
简单dp 都不会也是醉了
只需要想到,对于全排列从 x 到 x+1 长度增加1 对E的影响 要么就不变,要么就+1
于是很简单就可以写出dp方程。。。
N简单的最短路,十个点,任何算法都能过。
- 周六日常训练,背包dp,树形dp,简单dp以及很多数学?
- 树形dp专题训练
- 树形DP 专题训练
- hdu1561 树形DP+背包
- hdu1561 树形dp 背包
- hdu1561,树形dp+背包
- hdu1011 树形dp背包
- poj1155树形dp+背包
- POJ1155-树形DP&&背包
- hdoj4705Y【树形dp+简单组合数学】
- 背包dp训练总结
- HDOJ-4276(树形DP+背包DP)
- codeforce337D -----简单树形DP
- poj2342 简单树形DP
- POJ1463 简单树形DP
- POJ3140 简单树形DP
- 树形dp简单总结
- POJ2342 简单树形dp
- Retrofit使用总结
- 语音学习笔记13------谈谈斯坦福大学卷积神经网络之反向传播
- POJ 3126 Prime Path (BFS)
- CentOS环境下elasticsearch集群搭建
- javascript基础
- 周六日常训练,背包dp,树形dp,简单dp以及很多数学?
- Android视图状态及重绘流程分析,带你一步步深入了解View(三)
- Swift 3 编程语言
- 对url字符串中域名的三种截取方式
- WebStorm基本使用
- java中方法的参数传递机制
- 用WordNet实现中文情感分析
- java注释
- 每日一道算法题4——在二元树中找出和为某一值的所有路径