今天是大年初一,但是我的心情并不怎么样。感觉过年了老家人也多了,人多了就不清净了。也不会浮躁,就是心里老是烦。这两天的学习效率远比不上之前,得赶紧调整。
今天结了概率一章的内容,最后的两道例题都没看懂,概率还需要继续学习积累沉淀。
POJ3071 Football (http://poj.org/problem?id=3071)
与其说是DP,更像是递推,递推方程很好想,关键在于计算第i轮第k支球队可能碰到的对手,书上的计算方式看不懂,网上也找了不少博客,都大同小异。之后突然就茅塞顿开。首先很容易发现第i轮k的对手是从某个队伍j开始的连续2i-1支球队,这样只要找到这个起始对手j就可以做了。如何找j?为了方便找规律,队伍从0开始编号,为什么?因为牵扯到二进制,如果从1开始编号,那么最后一支球队会成为所有球队中唯一一支二进制位数为n的球队,那么在进行移位操作时就会造成不统一,这也是网上的算法都是 (i-1)>>1^1=(j-1)>>1的原因。所以从0开始编号更符合计算机的思维。这样一来我们尝试找规律。在第一轮两支交战队伍(i,j)满足i^1=j。第二轮(i,j)满足(i>>1^1=j>>1)。第三轮(i,j)满足(i>>2^1=j>>2)......化为一般形式,在第i轮交战的双方必须满足(p>>(i-1)^1=q>>(i-1))。形象的理解就是我们考虑第i轮的交战双方时就略去所有之前的二进制位,略去之后两支球队相邻那么在第i轮他们就可以对战。我们第二重循环枚举的是每支球队,网上有算法是对于球队i,再开一重循环枚举所有的球队j,判断是否满足上述条件。这样无疑会提高程序的运行时间,就比如说在第一轮时,每支球队只可能有一个对手,而该算法将枚举2n支球队。这也是对题目理解不透彻的结果。一开始我们就说了,会是连续的球队,因此我们只要用以下方式找出起始的球队j就好了。j=(k>>(i-1)^1<<(i-1))。这样就保证了所有枚举到的球队在二进制第i位是与k互异且比i高的进制位值是相同的的。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; const int M=1<<7; double dp[M+7][M+7],p[M+7][M+7]; int main() { int n; while(scanf("%d",&n)==1) { if(n==-1) break; memset(dp,0,sizeof(dp)); int m=1<<n; for(int i=0;i<m;i++) for(int j=0;j<m;j++) scanf("%lf",&p[i][j]); for(int i=0;i<m;i++) dp[0][i]=1; for(int i=1;i<=n;i++) for(int j=0;j<m;j++) { int l=(j>>i-1^1)<<(i-1); int r=l+(1<<i-1); for(int k=l;k<r;k++) dp[i][j]+=dp[i-1][j]*dp[i-1][k]*p[j][k]; } double ans=0; int team=0; for(int i=0;i<m;i++) if(dp[n][i]>ans) { ans=dp[n][i]; team=i; } printf("%d\n",team+1); } return 0; }
洛谷1291 [SHOI2002]百事世界杯之旅 (https://www.luogu.org/problemnew/show/P1291)
公式还可以,要注意通分约分的过程。
POJ2454 Jersey Politics (http://poj.org/problem?id=2454)
随机算法,先从小到大排序,然后选出前2*k个数划分成两个集合,再随机交换两个集合中的元素直到满足条件为止。
POJ3318 Matrix Multiplication (http://poj.org/problem?id=3318)
Ο(n3)直接矩阵乘法会TLE,问题就在于我们并不需要计算出实际的结果,只要检验给的结果是否正确。就像NOIP某年的等价表达式那道题一样,我们不需要真的需判断表达式是否等价,只要带几个数检验一下就行了。同样的思想,之所以复杂度高是因为我们对两个n*n的矩阵进行相乘,而等号两边同乘一个数等号依然成立,对于矩阵,我们就同乘一个矩阵,为了优化复杂度同时满足矩阵乘法的条件,很容易想到用一个n*1的检验矩阵。这样矩阵相乘的时间就是Ο(n2)的了,再Ο(n)比较乘出来的结果是否相等。检验矩阵的元素应该随机的,检验矩阵的个数就是算法总时间复杂度的常数,在不清楚概率的情况下,可以根据数据确定一个保证不超时的次数。
今天本来还有一道概率题是用模拟退火和爬山算法做的物理题,感觉网上的模拟退火都很虚,以后再写吧。其实晚上本来还准备写Splay的,但是感觉会调很长时间,那就又不能按时睡觉了,明天又要困了,今天为啥我没空写数据结构,因为我吃完饭从一点一下睡到五点,眼睛真的睁不开啊,根本不想看屏幕。
“每一次深情眼光的背后,谁知道会有多少愁。”