看注释。。。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#define LL long long
using namespace std;
const int maxn=110;
const int inf=0x3f3f3f3f;
int a[maxn],sum[maxn];
int dp[maxn][maxn];
int main()
{
int t,cas=0;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
for(int i=1;i<=n;i++)dp[i][i]=0;
for(int i=1;i<n;i++)
{
for(int j=1;j+i<=n;j++)
{
int tmp=j+i;
dp[j][tmp]=inf;
for(int k=j;k<=tmp;k++)
{
dp[j][tmp]=min(dp[j][tmp],(k-j)*a[j]+dp[j+1][k]+(sum[tmp]-sum[k])*(k-j+1)+dp[k+1][tmp]);
//如果是第k个出,则要加上dp[i][k],这个区间有k-1个,再加上(k-i)*a[i]
//然后还要加上后面的部分,即dp[[k+1][tmp],这部分已经算好了,所以我们同意给他们加上(k-j+1)*这部分的区间和
}
}
}
printf("Case #%d: %d\n",++cas,dp[1][n]);
}
return 0;
}
HDU - 2476
看注释。。
太难了区间dp,尽量从小方面考虑,同时还要考虑好各种情况。。。。
#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
#include<bitset>
#include<unordered_map>
using namespace std;
#define LL long long
#define eps (1e-9)
typedef unsigned long long ull;
const int maxn = 1e2 + 10;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const int bas = 131;
const LL mod = 1e9 + 7;
char s1[maxn], s2[maxn];
int dp[maxn][maxn];
int ans[maxn];
int main()
{
while (~scanf("%s%s", s1 + 1, s2 + 1))
{
int len = strlen(s1 + 1);
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= len; i++)dp[i][i] = 1;
for (int i = 1; i < len; i++)
{
for (int j = 1; i + j <= len; j++)
{
int tmp = j + i;
dp[j][tmp] = dp[j + 1][tmp] + 1;//最差的情况
for (int k = j + 1; k <= tmp; k++)
{
if (s2[j] == s2[k])dp[j][tmp] = min(dp[j][tmp], dp[j + 1][k] + dp[k + 1][tmp]);
//等于时说明可以先刷j到k,所以此时j到k的次数等于j+1到k
else dp[j][tmp] = min(dp[j][tmp], dp[j + 1][k] + dp[k + 1][tmp] + 1);
//不等于就多刷一次
}
}
}
//cout << dp[1][len] << endl;
for (int i = 1; i <= len; i++)
{
ans[i] = dp[1][i];
if (s1[i] == s2[i])
{
ans[i] = ans[i - 1];
//等于时我们只要刷前面的就好了,所以直接等于i-1的答案
}
for (int j = 1; j < i; j++)
{
ans[i] = min(ans[i], ans[j] + dp[j + 1][i]);
//枚举每一个小小区间
}
}
printf("%d\n", ans[len]);
}
return 0;
}