1. 程式人生 > >暑假訓練-訓練8 區間DP

暑假訓練-訓練8 區間DP

A - 石子歸併
Time Limit:1000MS Memory Limit:131072KB 64bit IO Format:%lld & %llu
Submit

Status
Description
現在有n堆石子,第i堆有ai個石子。現在要把這些石子合併成一堆,每次只能合併相鄰兩個,每次合併的代價是兩堆石子的總石子數。求合併所有石子的最小代價。

Input
第一行包含一個整數T(T<=50),表示資料組數。
每組資料第一行包含一個整數n(2<=n<=100),表示石子的堆數。
第二行包含n個正整數ai(ai<=100),表示每堆石子的石子數。

Output
每組資料僅一行,表示最小合併代價。

Sample Input
2
4
1 2 3 4
5
3 5 2 1 4
Sample Output
19
33

A:
F[i][j]表示在[i,j]上的最優解

#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h> #include<iostream> #include<sstream> #include<set> using namespace std; const int MAX=105; const int INF=99999999; int A[MAX],sum[MAX],F[MAX][MAX]; int main() { int T,n; scanf("%d",&T); while(T--) { memset(sum,0,sizeof(sum)); memset
(F,0,sizeof(F)); scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d",&A[i]); sum[i]=sum[i-1]+A[i]; } for (int l=2;l<=n;l++) { for (int i=1;i<=n-l+1;i++) { int j=i+l-1; F[i][j]=INF; for (int k=i;k<j;k++) { F[i][j]=min(F[i][j],F[i][k]+F[k+1][j]+sum[j]-sum[i-1]); //cout<<"F["<<i<<"]["<<j<<"]="<<F[i][j]<<endl; } } } printf("%d\n",F[1][n]); } return 0; }

B - Brackets
Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu
Submit

Status
Description
We give the following inductive definition of a “regular brackets” sequence:

the empty sequence is a regular brackets sequence,
if s is a regular brackets sequence, then (s) and [s] are regular brackets sequences, and
if a and b are regular brackets sequences, then ab is a regular brackets sequence.
no other sequence is a regular brackets sequence
For instance, all of the following character sequences are regular brackets sequences:

(), [], (()), ()[], ()[()]

while the following character sequences are not:

(, ], )(, ([)], ([(]

Given a brackets sequence of characters a1a2 … an, your goal is to find the length of the longest regular brackets sequence that is a subsequence of s. That is, you wish to find the largest m such that for indices i1, i2, …, im where 1 ≤ i1 < i2 < … < im ≤ n, ai1ai2 … aim is a regular brackets sequence.

Given the initial sequence ([([]])], the longest regular brackets subsequence is [([])].

Input
The input test file will contain multiple test cases. Each input test case consists of a single line containing only the characters (, ), [, and ]; each input test will have length between 1 and 100, inclusive. The end-of-file is marked by a line containing the word “end” and should not be processed.

Output
For each input case, the program should print the length of the longest possible regular brackets subsequence on a single line.

Sample Input
((()))
()()()
([]])
)[)(
([][][)
end
Sample Output
6
6
4
0
6




B:
F[i][j]表示[i,j]範圍內的合法數

#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
const int MAX=105;
const int INF=99999999;
int F[MAX][MAX];
int main()
{
    string s;
    while(cin>>s&&s[0]!='e')
    {
        int len=s.length();
        s.insert(0,1,' ');
        memset(F,0,sizeof(F));
        for (int l=2;l<=len;l++)
        {
            for (int i=1;i<=len-l+1;i++)
            {
                int j=i+l-1;
                if ((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']'))
                    F[i][j]=F[i+1][j-1]+2;
                for (int k=i;k<j;k++)
                {
                    F[i][j]=max(F[i][j],F[i][k]+F[k+1][j]);
                }
            }
        }
        cout<<F[1][len]<<endl;
    }
    return 0;
}

C - Halloween Costumes
Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu
Submit

Status
Description
Gappu has a very busy weekend ahead of him. Because, next weekend is Halloween, and he is planning to attend as many parties as he can. Since it’s Halloween, these parties are all costume parties, Gappu always selects his costumes in such a way that it blends with his friends, that is, when he is attending the party, arranged by his comic-book-fan friends, he will go with the costume of Superman, but when the party is arranged contest-buddies, he would go with the costume of ‘Chinese Postman’.

Since he is going to attend a number of parties on the Halloween night, and wear costumes accordingly, he will be changing his costumes a number of times. So, to make things a little easier, he may put on costumes one over another (that is he may wear the uniform for the postman, over the superman costume). Before each party he can take off some of the costumes, or wear a new one. That is, if he is wearing the Postman uniform over the Superman costume, and wants to go to a party in Superman costume, he can take off the Postman uniform, or he can wear a new Superman uniform. But, keep in mind that, Gappu doesn’t like to wear dresses without cleaning them first, so, after taking off the Postman uniform, he cannot use that again in the Halloween night, if he needs the Postman costume again, he will have to use a new one. He can take off any number of costumes, and if he takes off k of the costumes, that will be the last k ones (e.g. if he wears costume A before costume B, to take off A, first he has to remove B).

Given the parties and the costumes, find the minimum number of costumes Gappu will need in the Halloween night.

Input
Input starts with an integer T (≤ 200), denoting the number of test cases.

Each case starts with a line containing an integer N (1 ≤ N ≤ 100) denoting the number of parties. Next line contains N integers, where the ith integer ci (1 ≤ ci ≤ 100) denotes the costume he will be wearing in party i. He will attend party 1 first, then party 2, and so on.

Output
For each case, print the case number and the minimum number of required costumes.

Sample Input
2
4
1 2 1 2
7
1 2 1 1 3 2 1
Sample Output
Case 1: 3
Case 2: 4


C: F[i][j]表示在區間[i,j]內需要的最小衣服數量.首先初始化為j-i+1(最大值),F[i][j]=F[i+1][j]+1;
   F[i][j]=min(F[i][j],F[i+1][k-1]+F[k][j]) 找到與第i個相同的(k),分解成兩個子問題.

#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
const int MAX=105;
const int INF=99999999;
int T,N,A[MAX],F[MAX][MAX];
int main()
{
    cin>>T;
    for (int a=1;a<=T;a++)
    {
        memset(F,0,sizeof(F));
        cin>>N;
        for (int i=1;i<=N;i++)
        {
            cin>>A[i];
        }
        for (int i=1;i<=N;i++)
            for (int j=i;j<=N;j++)
                F[i][j]=j-i+1;
        for (int l=2;l<=N;l++)
        {
            for (int i=N-l+1;i>=1;i--)
            {
                int j=i+l-1;
                F[i][j]=F[i+1][j]+1;
                for (int k=i+1;k<=j;k++)
                {
                    if (A[k]==A[i])
                    {
                        F[i][j]=min(F[i][j],F[i+1][k-1]+F[k][j]);
                    }
                }
            }
        }
        cout<<"Case "<<a<<": "<<F[1][N]<<endl;
    }
    return 0;
}

D - You Are the One
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Submit

Status
Description
  The TV shows such as You Are the One has been very popular. In order to meet the need of boys who are still single, TJUT hold the show itself. The show is hold in the Small hall, so it attract a lot of boys and girls. Now there are n boys enrolling in. At the beginning, the n boys stand in a row and go to the stage one by one. However, the director suddenly knows that very boy has a value of diaosi D, if the boy is k-th one go to the stage, the unhappiness of him will be (k-1)*D, because he has to wait for (k-1) people. Luckily, there is a dark room in the Small hall, so the director can put the boy into the dark room temporarily and let the boys behind his go to stage before him. For the dark room is very narrow, the boy who first get into dark room has to leave last. The director wants to change the order of boys by the dark room, so the summary of unhappiness will be least. Can you help him?
Input
  The first line contains a single integer T, the number of test cases. For each case, the first line is n (0 < n <= 100)
  The next n line are n integer D1-Dn means the value of diaosi of boys (0 <= Di <= 100)
Output
  For each test case, output the least summary of unhappiness .
Sample Input
2
  
5
1
2
3
4
5

5
5
4
3
2
2
Sample Output
Case #1: 20
Case #2: 24



D: F[i][j]表示在區間[i,j]中的最小值 小黑屋是一個棧 假設i第k個上場 則分解為F[i+1][i+k-1]和F[i+k][j]

#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
const int MAX=105;
const int INF=99999999;
int T,N,A[MAX],F[MAX][MAX],SUM[MAX];
int main()
{
    cin>>T;
    for (int a=1;a<=T;a++)
    {
        memset(F,0,sizeof(F));
        memset(SUM,0,sizeof(SUM));
        cin>>N;
        for (int i=1;i<=N;i++)
        {
            cin>>A[i];
            SUM[i]=SUM[i-1]+A[i];
        }
        for (int l=2;l<=N;l++)
        {
            for (int i=1;i<=N-l+1;i++)
            {
                int j=i+l-1;
                F[i][j]=INF;
                for (int k=1;k<=j-i+1;k++)
                {
                    F[i][j]=min(F[i][j],F[i+1][i+k-1]+(k-1)*A[i]+F[i+k][j]+k*(SUM[j]-SUM[i+k-1]));
                }
            }
        }
        cout<<"Case #"<<a<<": "<<F[1][N]<<endl;
    }
    return 0;
}

E - Multiplication Puzzle
Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu
Submit

Status
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 product of the number on the card taken and the numbers on the cards on the left and on the right of it. It is not allowed to take out the first and the last card in the row. After the final move, only two cards are left in the row.

The goal is to take cards in such order as to minimize the total number of scored points.

For example, if cards in the row contain numbers 10 1 50 20 5, player might take a card with 1, then 20 and 50, scoring
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 cards N (3 <= N <= 100). The second line contains N integers in the range from 1 to 100, separated by spaces.
Output
Output must contain a single integer - the minimal score.
Sample Input
6
10 1 50 50 20 5
Sample Output
3650


E:
F[i][j]表示在[i,j)區間的最優解

#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
const int MAX=105;
const int INF=99999999;
int A[MAX],F[MAX][MAX];
bool used[MAX];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(F,0,sizeof(F));
        for (int i=0;i<MAX;i++)
            used[i]=false;
        for (int i=1;i<=n;i++)
            scanf("%d",&A[i]);
        for (int l=2;l<=n-1;l++)
        {
            for (int i=2;i<=n-l+1;i++)
            {
                int j=i+l-1;
                F[i][j]=INF;
                for (int k=i;k<j;k++)
                {
                    F[i][j]=min(F[i][j],F[i][k]+F[k+1][j]+A[i-1]*A[k]*A[j]);
                    //cout<<"F["<<i<<"]["<<j<<"]="<<F[i][j]<<endl;
                }
            }
        }
        cout<<F[2][n]<<endl;
    }
    return 0;
}

F - Running
Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu
Submit

Status
Description
The cows are trying to become better athletes, so Bessie is running on a track for exactly N (1 ≤ N ≤ 10,000) minutes. During each minute, she can choose to either run or rest for the whole minute.

The ultimate distance Bessie runs, though, depends on her ‘exhaustion factor’, which starts at 0. When she chooses to run in minute i, she will run exactly a distance of Di (1 ≤ Di ≤ 1,000) and her exhaustion factor will increase by 1 – but must never be allowed to exceed M (1 ≤ M ≤ 500). If she chooses to rest, her exhaustion factor will decrease by 1 for each minute she rests. She cannot commence running again until her exhaustion factor reaches 0. At that point, she can choose to run or rest.

At the end of the N minute workout, Bessie’s exaustion factor must be exactly 0, or she will not have enough energy left for the rest of the day.

Find the maximal distance Bessie can run.

Input
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Line i+1 contains the single integer: Di

Output
* Line 1: A single integer representing the largest distance Bessie can run while satisfying the conditions.
 

Sample Input
5 2
5
3
4
2
10
Sample Output
9


F:



#include<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
const int MAX=10005;
const int INF=99999999;
int A[MAX],F[MAX][505]; //F[i][j] 第i分鐘疲勞值為j時的最大距離
int N,M;
int main()
{
    while(scanf("%d%d",&N,&M)!=EOF)
    {
        memset(F,0,sizeof(F));
        for (int i=1;i<=N;i++)
            scanf("%d",&A[i]);
        for (int i=1;i<=N;i++)
        {
            for (int j=1;j<=M&&j<=i;j++)
                F[i][j]=F[i-1][j-1]+A[i];
            F[i][0]=F[i-1][0];
            for (int j=1;j<=M&&i-j>=0;j++)
                F[i][0]=max(F[i-j][j],F[i][0]);
        }
        cout<<F[N][0]<<endl;
    }
    return 0;
}