摘要:
题意:略。思路:进行两次dp。第一次dp从前向后,用dp[x]表示从第x位向前dp[x]位可构成一个数字,且与前面的数组符合题意要求。最后求的dp[n]即为最后一个数字的长度。而题目还有要求,所有解中输出前面数字最大的一个。因此还需要进行一次dp,从后向前。具体看代码吧,当初也是看别人代码才看懂的。 1 #include 2 #include 3 char num[85]; 4 int dp[85], n; 5 bool judge(int st1,int len1,int st2,int len2) 6 { 7 while (num[st1] == '0' && 阅读全文
摘要:
题意:略。思路:这是个删边的博弈游戏。关于删边游戏的预备知识:http://blog.csdn.net/acm_cxlove/article/details/7854532学习完预备知识后,这一题就不难了。首先,用tarjan算法找到每棵树中的双连通分量(即树枝上的多边形),根据Fusion Principle,如果多边形有奇数条边,可以简化为1条边,如果有偶数条边,则可以简化为1个点。代码中使用了vis数组,对于前者,使环内所有的点(包括悬挂点)的vis值为1,后面计算sg值时便不会再进行遍历这些点;对于后者,除了悬挂点和多边形内与悬挂点相邻的一点(相邻点中只取一个)外,多边形内其他点vis 阅读全文
摘要:
Nim游戏:有n堆石子,每堆个数不一,两人依次捡石子,每次只能从一堆中至少捡一个。捡走最后一个石子胜。先手胜负:将所有堆的石子数进行异或(xor),最后值为0则先手输,否则先手胜。================================Anti-Nim游戏:游戏与Nim游戏基本相同,只是捡走最后一个石子者输。先手胜负:将所有堆的石子数进行异或(xor),如果异或结果为0且所有堆的石子数全为1,或者异或结果为0且存在数量大于1的石子堆,则先手胜。否则先手输。该题即是Anti-Nim游戏,知道判定的规则后很简单。 1 #include 2 #include 3 using namespac 阅读全文
摘要:
题意:一个仅有一行的棋盘上,初始时有n个棋子,每人轮流移动棋子,每次只能移动一枚棋子,棋子在移动时只能向左移动,不能跨过别的棋子或跳出棋盘。思路:这道题是一道nim游戏的巧妙变形,太棒了。解决的思路是,将所有棋子的初始坐标从小到大排序,从最后一枚向前两两配对。如果棋子数为奇数,则将第一枚与坐标0配对。这样配对之后,如果移动一对中靠左的棋子,后一个人总可以移动靠右的那一枚棋子来保持两枚间距不变。这样靠左的棋子和前一对中靠右的棋子的距离就可以不需要考虑了,因为是不影响胜负的。唯一影响胜负的就是一对中的两枚棋子的距离。把所有对中的两枚棋子的距离看作一堆堆的石子,则可以把缩短距离看作捡石子,这样子谁先 阅读全文
摘要:
题意:n枚硬币围成一个圈,每次每个人可以从中取走一枚或者相邻的两枚(如果两枚硬币原本中间隔着一枚硬币,后来被取走,这两枚硬币不算相邻)。谁取走最后一枚硬币谁就赢了。思路:我们可以找找规律。首先,n为1和2的时候肯定是先手胜。n为3时,无论先手取1枚还是2枚,都会输。当n大于等于4时,我们分成两种情况来讨论。如果n为偶数,对于后手来说,总可以根据先手的做法,在对称的位置取走相同数量的硬币。先手必输。如果n为奇数,对于后手来说,总可以在某处取走硬币后,使得剩下的硬币分成对称的两组,然后依照n为偶数时的策略就能赢。此时也是先手必输。下面举个例子,假设n为5时,后手的策略如下图:PS:终于明白为什么这 阅读全文
摘要:
题意:威佐夫博弈。思路:看了很多证明都没看懂。最后决定就记住结论好了。对于所有的奇异局面(必败局),有通项公式Pi = (a, b), (a = i * [(sqrt(5) + 1) / 2], b = a + i) 其中[]表示取整,如[3.9] = 3, [4.1] = 4。那个(sqrt(5) + 1) / 2就是传说中的黄金分割了。根据这个通项公式,可以发现a与b之间的关系,a = (b - a) * [(sqrt(5) + 1) / 2]。因此对于一个给定的局面(a, b),只要判断其是否有这个关系就知道是不是必败了。此外还要注意,如果a > b,应将两者的值互换一下,这是为了 阅读全文
摘要:
题意:两个人做游戏,每个人都可以在自己的回合里将数p乘以2到9之间的一个数,初始时p=1,谁先将p乘到大于等于n就算赢。思路:一开始我算sg值,结果算来算去都没算明白。。。后来看了别人题解,才豁然开朗。首先,对于一个数m,计算出p在什么范围内可以乘到大于等于m。该范围即为[ceil(m/9), m - 1]。其中ceil()为向上取整。如果将每一个数字都看作一个局面的话,则在该区间内的点即为N点。对于一个数m,计算出p在什么范围内只能乘到大于等于m。该范围即为[ceil(m/2), m - 1]。如果将每一个数字都看作一个局面的话,且m对应的局面为N点时,则在该区间内的点即为P点。考虑到int 阅读全文
摘要:
题意:略。思路:用dp[i][k]来表示结点i给k个用户提供节目时的最大盈利(可能为负)。则递推方程为: dp[i][j] = max(dp[i][j], dp[i][m] + dp[v][j-m] - cost)其中v为i的孩子,cost为i向v提供节目的花费。另外注意代码里dp过程的这几行1 for (int j = num[x]; j >= 0; j--)2 for (int k = 1; k 2 #include 3 #include 4 #define maxn 3005 5 #define inf 0x3f3f3f3f 6 using na... 阅读全文
摘要:
题意:一棵树每个结点上都有值,现删掉一条边,使得到的两棵树上的数值和差值最小。思路:这个题我直接dfs做的,不知道树状dp是什么思路。。一开始看到数据规模有些后怕,后来想到long long 可以达到10^18,我突然就释然了。整体思路就是,先记录下整棵树的数值之和tot,然后对这棵树进行一遍dfs,每个结点都维护一个num值,num[x]表示结点x和它子树上的数值和。每求出一个结点的num值,就计算下tot - num[x]和num[x]的差值。dfs结束后最小的差值即为结果。另外,要注意的一点是,如果用res来存储最后结果,初始化应为无穷大,而因为它是long long类型,可以初始化为0 阅读全文
摘要:
题目:一棵树,每个结点上都有一些苹果,且相邻两个结点间的距离为1。一个人从根节点(编号为1)开始走,一共可以走k步,问最多可以吃多少苹果。思路:这里给出数组的定义:dp[0][x][j] 为从结点x开始走,一共走j步,且j步之后又回到x点时最多能吃到的苹果数。dp[1][x][j] 为从结点x开始走,一共走j步最多能吃到的苹果数(不必再回到x点)。之所以要定义上面的一种状态是因为在求第二种状态时需要用到。下面介绍递推公式。对于结点x,假设它目前要访问的孩子为y,则1...(y-1)已经遍历过。此时有:dp[0][x][j+2] = max(dp[0][x][j], dp[0][x][m] + 阅读全文