• URAL 1225 Flags 简单DP,一重循环


    题意:

    窗口可放n面红蓝白三种旗,规定同色不相邻,蓝在红白之间。共有多少种放置方法。

    思路:

    设dp[i][j]表示有i面旗,第i面旗填颜色j(j=01表示红白)时的总数,第i面填j色时,i-1可以填1-j(红白相间)或者蓝色,两种填法的计算:

    (1)填1-j时有dp[i-1][1-j]种   

    (2)填蓝色时i-2和i要填红白色才能将i-1的蓝色包围,即i-2要填1-j,共dp[i-2][1-j]种

    所以,状态转移方程为dp[i][j]=dp[i-1][1-j]+dp[i-2][1-j]。答案是dp[n][1]+dp[n][0]。

    空间优化:

    每一轮循环都要计算

    dp[i][0] = dp[i-1][1]+dp[i-2][1]

    dp[i][1] = dp[i-1][0]+dp[i-2][0]

    两式相加得:(dp[i][0] + dp[i][1]) = (dp[i-1][0]+ dp[i-1][1]) + (dp[i-2][0]+dp[i-2][1])

    两两结构相同,去掉第二维,dp[i] 表示前i面旗的放置方法总数,第i面旗可以填红白色。

    由上面的方程得:dp[i] = dp[i-1] + dp[i-2]

    直接给dp[i]分类很快,就是凑题解字数时,发现这种降维的方法,和背包的降维不一样。

    状态转移分析:

    第i面红色,i-1面白色:dp[i-1]是i-1填红白色的总数,红白各一半,白色有dp[i-1]/2种

    第i面红色,i-1面蓝色:i-2必须是白色,则有dp[i-2]/2种

    第i面白色,i-1面红色:同第一种,有dp[i-1]/2种

    第i面白色,i-1面蓝色:同第二种,有dp[i-2]/2种

    四个加起来得到dp[i]。

    初始化:

    dp[i]依赖于前两个,所以至少要提供两个连续的dp[i],可以是dp[0] dp[1]或dp[1] dp[2]

    算法步骤:

    步骤1:初始化为dp[i]=0,dp[1]=2

    步骤2:递推求dp[i],答案是dp[n]

    算法复杂度:

    初始化和递推都是一个循环,时间复杂度O(n),空间复杂度O(n)

    代码:

    #include <cstdio>
    const int MAX_N = 46;
    long long int cnt[MAX_N];
    int main() 
    { 
        int n;
        scanf("%d", &n);
        cnt[1] = cnt[2] = 2;
        for (int i = 3; i <= n; ++i)
            cnt[i] = cnt[i - 1] + cnt[i - 2];
        printf("%lld
    ", cnt[n]);
        return 0;
    }
       

    突然想到前面那个完全背包的输入,第i个物品用完就不用了,不用用数组保存。

    这道题只要维护三个值dp[i] dp[i-1] dp[i-2]就可以了,也就是

    c = a + b; 
    b = a; 
    a = c;  -> a+b未更新
    
    就是
    
    a = a + b; 
    b = a – b; // (a旧值+b)-b

    维护两个变量就行了OoO ,循环用while连for里面的局部变量也省了,代码好短

    算法步骤见代码,main函数四行,一行输入,一行计算,一行输出,一行return 0

    代码:

    #include <cstdio> 
    int n;
    long long a=2,b=0;  // a=[1] b=a[0] 
    int main() 
    { 
        scanf("%d", &n);  
        while(--n)  a = a + b , b = a - b;  
        printf("%lld
    ", a); 
        return 0;
    }

      

  • 相关阅读:
    [Swift]LeetCode1093. 大样本统计 | Statistics from a Large Sample
    [Swift]鸡尾酒排序 | Cocktail Sort
    [Swift]插入排序 | Insertion sort
    [Swift]求最大公约数和最小公倍数
    [Swift]LeetCode1087. 字母切换 | Permutation of Letters
    [Swift]LeetCode1086. 前五科的均分 | High Five
    [Swift]LeetCode1088. 易混淆数 II | Confusing Number II
    [Swift]LeetCode1090. 受标签影响的最大值 | Largest Values From Labels
    [Swift]LeetCode1091. 二进制矩阵中的最短路径 | Shortest Path in Binary Matrix
    [Swift]LeetCode1092. 最短公共超序列 | Shortest Common Supersequence
  • 原文地址:https://www.cnblogs.com/tinyork/p/5044050.html
Copyright © 2020-2023  润新知