男神的礼物
Time Limit: 3000/3000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
Lweb学长是集训队里公认的男神。有一天他要给美美的学姐姐准备礼物。
Lweb学长可是会魔法的哟。为了准备一份礼物,男神要加工n份材料。每一次只能加工相邻的材料。
当男神加工两个魔法值为a,b的材料,男神都要消耗a*b的体力,同时在这个地方合成出魔法值(a+b)%100的材料。
男神为了能节省体力来完成他的礼物。想找聪明的你帮他算一算他所要花费的最小体力。
Input
第一行一个整数T,表示男神所要准备的礼物数。 之后的T组数据各有两行数据,第一行有一个整数n,表示这份礼物的材料数(1<=n<=100)。 接下来一行有n个整数a(0<=a<100),表示这件礼物第i份材料的魔法值。
Output
每组数据一行输出,表示男神制作这份礼物所要的最小体力。
Sample input and output
Sample Input | Sample Output |
---|---|
2
2
18 19
3
40 60 20
|
342
2400
|
Hint
对于样例 2:
先加工材料40和60,得到0的材料,消耗40∗∗60体力,共消耗2400体力;
再加工材料0和20,得到20的材料,消耗0∗∗20体力,共消耗2400体力.
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <map> #include <vector> #include <queue> #include <cstring> #include <string> #include <algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; #define MM(a,b) memset(a,b,sizeof(a)); #define inf 0x7f7f7f7f #define FOR(i,n) for(int i=1;i<=n;i++) #define CT continue; #define PF printf #define SC scanf const int mod=1000000007; const int N=1e3+10; int dp[105][105],sum[105]; int main() { int cas,n,x; scanf("%d",&cas); while(cas--) { MM(dp,inf);MM(sum,0); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&x); dp[i][i]=0; sum[i]=sum[i-1]+x; } for(int r=2;r<=n;r++) for(int l=r-1;l>=1;l--) for(int k=l;k<=r-1;k++) { int ener=((sum[k]-sum[l-1])%100)*((sum[r]-sum[k])%100); dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]+ener); } printf("%d ",dp[1][n]); } return 0; }
分析:设dp[l][r]为合并区间[l,r]范围材料的体力消耗,先固定l,r然后枚举中间值k(k代表将[l,k]和
[k+1,r]范围内的材料合并,当然前提是两边的数合并的结果已经算出来了),
dp[l][r]=min(dp[l][k]+dp[k+1][r]+消耗); 复杂度n^3;