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\n", dp[1][N - 2]);
50 }
时间: 2024-12-20 14:44:08

DP:Multiplication Puzzle(POJ 1651)的相关文章

Multiplication Puzzle POJ - 1651

10*1*50 + 50*20*5 + 10*50*5 = 500+5000+2500 = 8000 If he would take the cards in the opposite order, i.e. 50, then 20, then 1, the score would be 1*50*20 + 1*20*5 + 10*1*5 = 1000+100+50 = 1150. Input The first line of the input contains the number of

POJ 区间DP Multiplication Puzzle

The multiplication puzzle is played with a row of cards, each containing a single positive integer. During the move player takes one card out of the row and scores the number of points equal to the product of the number on the card taken and the numb

POJ 1651 区间DP Multiplication Puzzle

此题可以转化为最优矩阵链乘的形式,d(i, j)表示区间[i, j]所能得到的最小权值. 枚举最后一个拿走的数a[k],状态转移方程为d(i, j) = min{ d(i, k) + d(k, j) + a[i] * a[k] * a[j] } 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std;

poj 1651

hnldyhy// poj 1651 矩阵连乘 DP #include <iostream>#include <string.h>using namespace std;int dp[103][103],s[103];int main(){ int n,i,j,k,min; cin>>n; for(i=1;i<=n;++i) cin>>s[i]; memset(dp,0,sizeof(dp)); for(i=n-2;i>=1;--i) for(j

POJ 1651 Multiplication Puzzle (区间dp)

题目大意:对n个数组成的序列取数,规定最两边不能取,每次取一个a[i],得到 a[l] * a[i] * a[r] 的分数(a[l]是a[i]左边的数,a[r]是a[i]右边的数),并把这个数从序列中移走,求n-2次取数后的得分和的最小值 分析:正着确定状态不好做,不如反着来,设dp[l][r]为向区间[l, r]中填满数所得到分数和的最小值,考虑最近一次填数的位置,不难得出: dp[l][r] = fmin(dp[l][m] + dp[m][r] + a[l] * a[m] * a[r]) (

POJ 1651 Multiplication Puzzle(区间dp)

Language: Default Multiplication Puzzle Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6693   Accepted: 4083 Description The multiplication puzzle is played with a row of cards, each containing a single positive integer. During the move

POJ 1651:Multiplication Puzzle 矩阵相乘式DP

Multiplication Puzzle Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7118   Accepted: 4385 Description The multiplication puzzle is played with a row of cards, each containing a single positive integer. During the move player takes one

poj 1651 区间dp

题目链接:http://poj.org/problem?id=1651 Description The multiplication puzzle is played with a row of cards, each containing a single positive integer. During the move player takes one card out of the row and scores the number of points equal to the prod

Mark一下, dp状态转移方程写对,但是写代码都错,poj 1651 poj 1179

dp题: 1.写状态转移方程; 2.考虑初始化边界,有意义的赋定值,还没计算的赋边界值: 3.怎么写代码自底向上计算最优值 今天做了几个基础dp,全部是dp方程写对但是初始化以及计算写错 先是poj 1651 其实就是个赤裸裸的矩阵连乘,dp方程很容易写出 dp[i][j]=min(dp[i][k]+dp[k+1][j]+r[i]*c[k]*c[j],dp[i][j]); 先贴两个个二逼的代码,mark下自己多么的二逼: 二逼一:在计算的时候使用了还没有算出来的值,模拟下就知道第一重循环里算dp