POJ 搜索(2)

最优化剪枝和可行性剪枝

poj1699

搜索的技巧和优化

poj3411, poj1724

记忆化搜索

poj3373,poj1691

 

 

 

 

 

最优化剪枝和可行性剪枝

POJ 1699

对这题无语了,爆搞TLE,加一个怎么也没想到的减枝47MS...

规模并不大,可以直接dfs,需要预处理一下,add[i][j]表示第j号串加在第i号串上增加的长度。。。这个计算的时候要注意。本菜就错在这上边wa了一上午!。

 

搜索的技巧和优化 

poj 3411

题意:有m条路,N个顶点。从ai到bi的路要付费,付费有两种方式:1、比如之前去过ci,则可以在ci预付pi的费用。2、到达bi以后再付费,这样的费用是ri。求从1到N共的最小付费是多少。

题解:这题的规模不大,可以直接爆搞。但是,每条边的访问次数可以是多次。也就是说每个顶点可以访问多次,这样的话可以类似spfa的方法记录每一顶点的访问次数,当超过n次时conintue;当然还可以像POJ 1699一样加一个剪枝。cost记录dfs到当前的花费,如果cost >= ans则可以直接return;

poj 1724

题意:Bob要离家出走,从1号城市去N号城市。Bob手头有k money,每过一条路需要叫一点数目的money,否则不能通过,求在k money的承受范围内的最短路。

题解:话说3411时我想的一个错误的方法在这里居然可行,哈哈 ^_^。cat[u][v]表示u到v的边数。这样可以判出有环无环的情况,然后dfs。

View Code
void dfs(int u, int l, int k) {
    if(l >= ans)    return ;
    if(u == n) {
        ans = Min(ans, l);
        return ;
    }
    int v, i;
    for(i = head[u]; i != -1; i = g[i].next) {
        v = g[i].to;
        if(!cat[u][v] || k - g[i].tl < 0)   continue;

        cat[u][v] --; 
        dfs(v, l + g[i].ln, k - g[i].tl);
        cat[u][v] ++; 
    }
}

 

记忆化搜索

彻底败给3373了,本菜估计要错出3373应该要两天时间。。。T_T

POJ 1691 (状压dp)

题意:有一个棋盘,划分成n个方格,每个方格涂相应的颜色,图色方案如下:

1、方格i能够被涂色当且仅当i正上方相邻的方格都被涂色;

2、比如现在要涂col1色,则所有要涂col1色且满足条件以的方格可以同时涂色;

求喷头至少要换几次能把方格涂完。

思路:表示真心没相当状态压缩可以这样写,我一直在纠结要怎么预处理棋盘。。。T_T!

共n个方格,每方格i一给它一个编号 1<<i。所有的方格都被涂色后的状态是 (1<<n) - 1(等比数列求和公式,可以自己算一下,其实从状态累加上就可以看出来。)

dp[x][i]表示当前状态为x,最后一次涂色的方格是i时的最优值。

dp[ns][i]转移时可以枚举上一次最后涂色的方格是j的值dp[s][i],然后转移,ns = s|(1<<i),表示i从状态j转移后被染色得到的新状态。详见代码:

int solve() {
    int s, i, j;
    int m = E(n), tmp, ns;
    REP(i, m)   REP(j, n)   dp[i][j] = inf;
    REP(i, n)   if(!up[i])  dp[(1<<i)][i] = 1;    //第一行,上边没有方块时的情况。
    REP(s, m) {
        REP(i, n) {    //当前状态为s时选一个没有被染色的方格i进行转移。
            if(s&(1<<i))  continue;    //被染色
            if((s&up[i]) != up[i])    continue;    //方格i整上方的方格没有全被染色
            REP(j, n) {    //枚举上一次最后染色为方格j时的情况,通过这个情况转移到i。
                if((s&(1<<j)) == 0)   continue;    //j未被染色
                ns = s|(1<<i);   //转移到新状态
                tmp = dp[s][j];
                if(p[j].col != p[i].col)    ++tmp;    //颜色相同不用换喷头,颜色不同则要更换。
                dp[ns][i] = Min(dp[ns][i], tmp);
            }
        }
    }
    int res = inf;
    REP(i, n) {
        res = Min(res, dp[m- 1][i]);
    }
    return res;
}

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(poj)