USTC 2015 dpテーマA神様のプレゼント区間dp

9614 ワード

神の贈り物
Time Limit:20 Sec  メモリLimit:256 MB
タイトル接続
http://acm.uestc.edu.cn/#/contest/show/65
Description
Lweb先輩は合宿チームで公認されている男神です.ある日彼は美しい学姉さんにプレゼントを準備します.
Lweb先輩は魔法ができますよ.プレゼントを準備するために、神は材料を加工します.一回につき隣の材料しか加工できません.
神が二つの魔法の値を加工する時、神はa*bの体力を消耗します.同時にこの場所で魔法の値(a+b)%100の材料を合成します.
男性神は体力を節約するために彼のプレゼントを完成しました.賢い人を探したいですが、彼が使う最小体力を計算してください.
wijキログラムのケーキは、Gorwinが左上(1,1)の格子から歩いて、右下(n,m)の格子に行きます.各ステップにおいて、Gorwinは右または下に行くことができます.すなわち、Gorwinは(i,j)に立っているとき、彼女は(i+1,j)または(i,j+1)に向かうことができます.Gorwinが一つの格子に着いたら、彼女はその格子の中のケーキを食べてもいいですか?食べないでもいいです.しかし、彼女は一部だけを食べてはいけません.彼女は胃がそんなに大きくないので、Kキロのケーキしか食べられません.今、Gorwinは左上に立っています.彼女はケーキ園の地図を見ています.道を探したいです.彼女が食べられるケーキの一番多い道を探しています.助けてください.
Input
最初の行の整数Tは、男性の神が準備する贈り物の数を表しています.その後のTグループのデータはそれぞれ2行のデータがあります.1行目は整数nがあり、この贈り物の材料数を表しています.次の行はn個の整数a(0<=a<100)で、この贈り物のi番目の材料の魔法値を表します.
 
Output
各グループのデータを一行ずつ出力して、男性神がこのプレゼントを作るために必要な最小体力を表します.
Sample Input
2 18 19 3 40 60 20
Sample Output
342
2400
HINT
サンプル2:
まず40と60を加工して、0の材料を得て、40∗60の体力を消耗して、全部で2400の体力を消耗します.
更に材料を加工して0と20を得て、20の材料を得て、0〓20体力を消耗して、共に2400体力を消耗します.
題意
 
クイズ:
区間dp~
コード:
 
//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 200001
#define mod 10007
#define eps 1e-9
int Num;
char CH[20];
const int inf=0x7fffffff;   //нчоч╢С
/*

inline void P(int x)
{
    Num=0;if(!x){putchar('0');puts("");return;}
    while(x>0)CH[++Num]=x%10,x/=10;
    while(Num)putchar(CH[Num--]+48);
    puts("");
}
*/
inline ll read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void P(int x)
{
    Num=0;if(!x){putchar('0');puts("");return;}
    while(x>0)CH[++Num]=x%10,x/=10;
    while(Num)putchar(CH[Num--]+48);
    puts("");
}
//**************************************************************************************

ll dp[101][101];
ll a[101];
ll sum[101];
int main()
{
    int t=read();
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        memset(sum,0,sizeof(sum));
        int n=read();
        for(int i=1;i<=n;i++)
        {
            a[i]=read();
            sum[i]=a[i]+sum[i-1];
        }
        for(int r=2;r<=n;r++)
        {
             for(int i=r-1;i>=1;i--)
            {
                for(int j=i;j<=r;j++)
                {
                    ll kiss=((sum[j]-sum[i-1])%100)*((sum[r]-sum[j])%100);
                    if(dp[i][r]==0)
                        dp[i][r]=dp[i][j]+dp[j+1][r]+kiss;
                    else
                        dp[i][r]=min(dp[i][r],dp[i][j]+dp[j+1][r]+kiss);
                }
            }
        }

        cout<<dp[1][n]<<endl;
    }
}