if (days<=pay) return ( days*pay);
return ( pay*pay+getCoins(pay+1, days-pay));
}
blocks:
/*f[i][j][k]=Max{
Max{f[i][p][len[j]+k]+f[p+1][j-1][0]}(color[p]=color[j] and i<p<j)//和前面某段一起消掉
f[i][j-1][0]+sqr(len[j]+k)//马上消掉这一段
}*/
//*********** i:from max to min;j: from min to max,k:no matter
#include <stdio.h>
#include <string.h>
#include<alg.h>
//#include <algorithm>
//#include <iostream>
//using namespace std;
struct segment{
int color;
int len;
segment():color(0), len(0){}
};
const int max_n = 200;
int dp[max_n][max_n][max_n] = { 0 };
int main(){
int test = 0, t = 0;
int n = 0;
scanf("%d", &test);
for (t = 1; t <= test; ++t){
int nseg = 0, i = 0, j = 0;
int color;
scanf("%d", &n);
segment blocks[max_n];
scanf("%d", &blocks[nseg].color); ++blocks[nseg].len;
for (i = 1; i < n; ++i){
scanf("%d", &color);
if (color == blocks[nseg].color) ++blocks[nseg].len;
else{
blocks[++nseg].color = color;
++blocks[nseg].len;
}
}
//input END
++nseg;
memset(dp, 0, sizeof(dp));
int k = 0, ttry = 0;
for (i = nseg - 1; i >= 0;--i)
for (j = i; j < nseg; ++j){
for (k = 0; k <= n; ++k){
if (j == 0)
dp[i][j][k] = (blocks[j].len + k)*(blocks[j].len + k);
else{
dp[i][j][k] = dp[i][j - 1][0] + (blocks[j].len + k)*(blocks[j].len + k);
for (ttry = i; ttry < j; ++ttry){
if (blocks[ttry].color != blocks[j].color) continue;
dp[i][j][k] = max(dp[i][j][k], dp[i][ttry][k + blocks[j].len] + dp[ttry + 1][j - 1][0]);
}
}
}
}//DP
printf("Case %d: %d\n", t, dp[0][nseg - 1][0]);
}
return 0;
}
棋盘分割:
1. 数学化归最小方差
2. 计算(x1,y1,x2,y2)棋盘上的分数和,用和左上角连成的矩形分数加减
3. 可以DP,可以递归,思路是一样的。