POJ 1351 Number of Locks (记忆化搜索 状态压缩)

Number of Locks

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 1161   Accepted: 571

Description

In certain factory a kind of spring locks is manufactured. There are n slots (1 < n < 17, n is a natural number.) for each lock. The height of each slot may be any one of the 4 values in{1,2,3,4}( neglect unit ). Among the slots
of a lock there are at least one pair of neighboring slots with their difference of height equal to 3 and also there are at least 3 different height values of the slots for a lock. If a batch of locks is manufactured by taking all over the 4 values for slot
height and meet the two limitations above, find the number of the locks produced.

Input

There is one given data n (number of slots) on every line. At the end of all the input data is -1, which means the end of input.

Output

According to the input data, count the number of locks. Each output occupies one line. Its fore part is a repetition of the input data and then followed by a colon and a space. The last part of it is the number of the locks counted.

Sample Input

2
3
-1

Sample Output

2: 0
3: 8

Source

Xi‘an 2002

题目链接:http://poj.org/problem?id=1351

题目大意:用数字1,2,3,4求一个长度为n的序列,要求这个序列中至少有三个不同的数字且至少有一组相邻的值相差3,求满足条件的序列的个数

题目分析:dp[num][t][ok][last]表示当前序列长度为num,用了t种数字,若有有相邻的1,4则ok为1,否则为0,last表示当前序列的最后一个数,采用记忆化搜索,DFS里除了dp的4个值还要多一个参数st,用2进制表示当前数字的使用状态,例如st=1111表示四个数都用了,每次将搜索的数与当前状态与一下来判断使用个数有没有增加.

#include <cstdio>
#include <cstring>
#define ll long long
ll dp[20][5][2][5];
int n;

ll DFS(int num, int t, int ok, int last, int st)
{
    if(num == n)
    {
        if(t >= 3 && ok)
            return 1;
        else
            return 0;
    }
    if(dp[num][t][ok][last] != -1)
        return dp[num][t][ok][last];
    ll tmp = 0;
    for(int i = 1; i <= 4; i++)
    {
        int tt, ok2 = 0, curst = 1 << (i - 1);
        if((i == 1 && last == 4) || (i == 4 && last == 1))
            ok2 = 1;
        if(st & curst)
            tt = t;
        else
            tt = t + 1;
        if(tt > 3)
            tt = 3;
        tmp += DFS(num + 1, tt, ok || ok2, i, st | curst);
    }
    return dp[num][t][ok][last] = tmp;
}

int main()
{
    while(scanf("%d", &n) != EOF && n != -1)
    {
        memset(dp, -1, sizeof(dp));
        printf("%d: %lld\n", n, DFS(0, 0, 0, 0, 0));
    }
}
时间: 2024-10-17 08:02:05

POJ 1351 Number of Locks (记忆化搜索 状态压缩)的相关文章

hiho 1170(机器人-记忆化搜索+状态压缩)

#1170 : 机器人 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 小冰的N个机器人兄弟排成一列,每个机器人有一个颜色.现在小冰想让同一颜色的机器人聚在一起,即任意两个同颜色的机器人之间没有其他颜色的的机器人. 假设任意相邻的两个机器人可以交换位置,请问最少需要多少次交换? 输入 第一行为一个整数T,为数据组数,之后每组数据两行. 第一行为N和K,表示机器人的个数与颜色的总数. 接下来一行N个数,第i个数表示第i个机器人的颜色,取值范围为1到K. 输出 对于每组数

POJ 3249 Test for Job (记忆化搜索 好题)

Test for Job Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9512   Accepted: 2178 Description Mr.Dog was fired by his company. In order to support his family, he must find a new job as soon as possible. Nowadays, It's hard to have a job

poj 1661 Help Jimmy(记忆化搜索)

题目链接:http://poj.org/problem?id=1661 一道还可以的记忆化搜索题,主要是要想到如何设dp,记忆化搜索是避免递归过程中的重复求值,所以要得到dp必须知道如何递归 由于这是个可以左右移动的所以递归过程肯定设计左右所以dp的一维为从左边下或者从右边下,而且和层数有关所以另一维为层数 于是便可以得到dp[count][flag],flag=1表示count层从左边下要多久,flag=0表示count层从右边下要多久.然后就是dfs的递归 过程 #include <iost

poj 1579(动态规划初探之记忆化搜索)

Function Run Fun Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17843   Accepted: 9112 Description We all love recursion! Don't we? Consider a three-parameter recursive function w(a, b, c): if a <= 0 or b <= 0 or c <= 0, then w(a, b

poj 1088 动态规划+dfs(记忆化搜索)

滑雪 Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个 区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17 18 19 6

POJ 1579 Function Run Fun 记忆化搜索

Description We all love recursion! Don't we? Consider a three-parameter recursive function w(a, b, c): if a <= 0 or b <= 0 or c <= 0, then w(a, b, c) returns: 1 if a > 20 or b > 20 or c > 20, then w(a, b, c) returns: w(20, 20, 20) if a &

POJ 2192 &amp;&amp; HDU 1501 Zipper (记忆化搜索)

Zipper Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16803   Accepted: 5994 Description Given three strings, you are to determine whether the third string can be formed by combining the characters in the first two strings. The first tw

POJ 1088 滑雪 (DPor记忆化搜索)

题目大意:中文题:http://poj.org/problem?id=1088 先上一发自己写的记忆化,渣,900多毫秒 #include <iostream> #include <cstdio> #include <stack> #include <cstring> using namespace std; int a[111][111]; int visit[111][111]; int dp[111][111]; int dir[4][2] = {{1

poj 1198 / hdu 1401 Solitaire (记忆化搜索+meet in middle)

题目大意:给你一个8*8的棋盘,上面有四个棋子,给你一个初始排布,一个目标排布,每次移动,可以把一个棋子移动到一个相邻的空位,或者跨过1个相邻的棋子,在保证棋子移动不超过8次的情况下,问能否把棋盘上的棋子由初始排布变成目标排布 8*8的棋盘,刚好不爆ull,状压那些位置有棋子 然后从初始状态开始,暴搜出当前状态下,移动一个棋子之后所有可能到达的状态 直接搜,总状态数是8^8,此外还有常数,会爆 由于给定了目标排布,考虑meet in middle 从起始状态和目标状态各搜4步即可 为了防止爆栈,