zoukankan      html  css  js  c++  java
  • DP:Multiplication Puzzle(POJ 1651)

                      

                      卡片游戏

      题目大意:给你一排卡片,你可以从从中抽一些卡片(但是不能抽最左和最右的卡片),每张卡片上有一个数字,当你从中抽出一张卡片后,你将得卡片的数字和卡片左右两张卡片的数字的乘积的分数,问当剩下最左和最右两张卡片的时候,你可以得到的最小的分数

      这一题一看好像挺复杂的,但是如果我们换一个思维方式,这一题就会变得很熟悉

      首先这一题是显而易见的DP(找最小值,不能取极限方式)

      首先他要我们抽卡片是吧,一开始我们可能会想到先抽一张看看,然后在扫一遍其他卡片看能否抽,但是这样带来的直接后果就是,我们很难对先前我们抽过的卡片进行分数的储存,那么可以这么想,如果我们在抽卡片之前,把左i张右j张的卡片的抽取已经记下来了(相当于是抽空了),然后我们再把这张卡片和i-1和j+1的卡片的乘积+左i张和右j张卡片的分数加起来不就等于我们当前抽的卡片的分数了吗!那么最后我们就可以维护一个最小值区间,把区间不断扩大到n-2(除掉最左和最右两张),那得出的值即是最后的最小分数

      而这个方法,正是矩阵乘法的顺序安排的思路,熟悉而亲切

      

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 static long long cards[100];
     6 static long long dp[100][100];
     7 
     8 void Search(const int);
     9 long long min(const long long, const long long);
    10 
    11 int main(void)
    12 {
    13     int N, i;
    14     while (~scanf("%d", &N))
    15     {
    16         for (i = 0; i < N; i++)
    17             scanf("%d", &cards[i]);
    18         //memset(dp, 0, sizeof(dp));
    19         Search(N);
    20     }
    21     return 0;
    22 }
    23 
    24 long long min(const long long x, const long long y)
    25 {
    26     return x < y ?  x : y;
    27 }
    28 
    29 void Search(const int N)
    30 {
    31     int i, j, k, pos;
    32 
    33     for (i = 1; i < N - 1; i++)
    34         dp[i][i] = cards[i - 1] * cards[i] * cards[i + 1];
    35     for (k = 1; k < N - 2; k++)
    36     {
    37         for (i = 1; i < N - 1 - k; i++)
    38         {
    39             pos = i + k;
    40             dp[i][pos] = cards[i] * cards[i - 1] * cards[pos + 1] + dp[i + 1][pos];//注意cards的位置
    41             for (j = i + 1; j < pos; j++)
    42             {
    43                 dp[i][pos] = min(dp[i][pos],
    44                     cards[j] * cards[i - 1] * cards[pos + 1] + dp[i][j - 1] + dp[j + 1][pos]);
    45             }
    46             dp[i][pos] = min(dp[i][pos], cards[i - 1] * cards[pos] * cards[pos + 1] + dp[i][pos - 1]);
    47         }
    48     }
    49     printf("%lld
    ", dp[1][N - 2]);
    50 }
  • 相关阅读:
    如何给wordpress外部链接自动添加nofollow
    wordpress如何批量关闭旧日志留言功能
    如何一次把所有wordpress插件都禁用了
    sql批量获取wordpress所有留言者的邮件地址
    wordpress数据库优化-关闭日志修订
    wordpress数据库优化wp_posts表 OPTIMIZE
    sql批量删除wordpress所有日志修订revision
    sql删除wordpress没用的postmeta记录
    wordpress如何删除没有文章的tags标签
    批量删除wordpress垃圾评论留言
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/4852660.html
Copyright © 2011-2022 走看看