PKU 3371 Stake Your Claim
这道题比较好的算法(而且我只能用这个过)就是把空缺的10个空位用3进制状态压缩表示(0代表没放,1代表0号选手放的,2代表1号选手放的) 然后做记忆化搜索
我开始用的是AB剪枝 始终TLE 后来脑袋不清醒 在AB剪枝的同时加DP结果变成WA,后来想到AB剪枝的时候棋盘局面和剪枝有关 故不能随便DP
不知哪位高人能给与指点解决这个问题
下面是AB剪枝的大概流程,我们看到剪枝的时候返回值是跟sta(当前子局面中最优的)有关的,所以不能直接DP
 1说几道题目_职场
 2说几道题目_职场int search(int p, int sta) { //假定现在在计算S的子局面S2,sta则是S1的状态值
 3说几道题目_职场    if(p == 0) { //假定S局面取小,如果S2比S1大 则无用 即只要S2的子局面有一个比STA大 S2就无用了 退出
 4说几道题目_职场        int now = -MAXINT; //S2局面取大 初始化为最小
 5说几道题目_职场        for( every possible action ) {
 6说几道题目_职场            //go this action;
 7说几道题目_职场            int next = search(1now);
 8说几道题目_职场            now = Max(nownext); 
 9说几道题目_职场            //cancel this cation
10说几道题目_职场            if(now > sta) break; //S2的某个子局面出现了比sta还小的 退出
11说几道题目_职场        }
12说几道题目_职场        return now;
13说几道题目_职场    } 
14说几道题目_职场    else { //假定S局面取大,如果S2比S1小 则无用 即只要S2的子局面有一个比STA小 S2就无用了 退出
15说几道题目_职场        int now = MAXINT;
16说几道题目_职场        for( every possible action ) {
17说几道题目_职场            //go this action;
18说几道题目_职场            int next = search(1now);
19说几道题目_职场            now = Min(nownext);
20说几道题目_职场            //cancel this action
21说几道题目_职场            if(now < sta) break; 
22说几道题目_职场        }
23说几道题目_职场        return now;
24说几道题目_职场    }
25说几道题目_职场}
26说几道题目_职场

TJU2879   Little Peter's Tower
题目给你一个范围内的积木 让你随即按次序得到T个积木 问你怎么堆才能堆得最高
看到这题之后我一直以为题目要求我们找出一种最优策略
但是苦于概率上的不确定性 没有办法找出
没想到其实不是这样的 其实这是一个DP task。我们能够得知的策略就是如果我们只有一个积木 那么我们必然会堆一个 不管他有多高 那么如果我们定义这样的状态:
dp[top][time]  就可以得到下面的递推式:
dp[top][time] = 平均(max(dp[top][time-1], dp[k][time-1] + k); //k是高度
于是程序写出来倒是很短
说几道题目_职场#include <iostream>
说几道题目_职场using namespace std;
说几道题目_职场
说几道题目_职场
double dp[120][120];
说几道题目_职场
说几道题目_职场#define Max(a, b) ((a) 
> (b) ? (a) : (b))
说几道题目_职场
说几道题目_职场
int main() {
说几道题目_职场    
int R, H, T, i, j, k, r;
说几道题目_职场    
int ntc;
说几道题目_职场    scanf(
"%d"&ntc);
说几道题目_职场    
while(ntc--) {
说几道题目_职场        scanf(
"%d %d %d"&R, &H, &T);
说几道题目_职场        
for(i = 1; i <= R; ++i) dp[0][i] = 0;
说几道题目_职场        
for(i = 1; i <= T; ++i) {
说几道题目_职场            
for(r = 1; r <= R; ++r) {
说几道题目_职场                dp[i][r] 
= dp[i-1][r] * (R-r) * H;
说几道题目_职场                
for(j = 1; j <= r; ++j)
说几道题目_职场                    
for(k = 1; k <= H; ++k)
说几道题目_职场                        dp[i][r] 
+= Max(dp[i-1][r], dp[i-1][j] + k);
说几道题目_职场                dp[i][r] 
/= R * H;
说几道题目_职场            }
说几道题目_职场        }
说几道题目_职场        printf(
"%.6lf\n", dp[T][R]);
说几道题目_职场    }
说几道题目_职场    return 
0;
说几道题目_职场}

TJU2868   Fire Balloon
一个很好的枚举+DP的题目
其实题目很好转化成二分图 但是数据范围限制让我们不得不另寻他法
题目是一个有环图,这个环在与:
1.上下两个点之间存在连接
2.左右两端连接起来了
于是我们才与枚举状态 消除后效性做DP!
首先把纵向的2个格子合并成一个大的状态 这样就退化成了一个环
然后再在任意两点之间枚举两点之间的连接情况 这样就退化成了一条链
终于可以开始DP了 呵呵


PKU3265 Problem Solving
初看真的非常像贪心 结果是DP 隐藏的真好 推荐

TJU1037 Binary Search Tree I
这道题我居然不是观察数据 猜测 然后证明
而是直接证明了才作。。。
做法:排序所有的数
如果一个数x的左边那个数y和右边的z那个数都比x先插入 那么它是叶子
如果都比x后插入 也是叶子
这样证明:
二叉树的一个重要性质就是2分区间

比如插入一个8
就把分成了(-INF, 8] 和 [8, INF)
如果一个数x的左边那个数和右边那个数都比x先插入
那么他一定是叶子 为什么呢 如果他不是叶子
比如他有左子树 那么y一定在他的左子树里面
同理 可证明其他

PKU3304 Segments
又是一个要求转化的题目
题目给了一个映射共点的条件 几乎没什么用
但是一旦你想到转化成这一点出发的一条线会与所有线相交
问题立刻转化成了枚举端点 确定这条线!