1.点击打开链接
消除颜色相同的k个连续格子,可以得到的分数为k*k,问最大的的得分为多少?
dp记忆化搜索。
dp[i][j][k]从i点到j点,j点后有k个和j点颜色相同的格子。
两种情况:一是直接消除j点及其后面相等的k个格子,获得(k+1)*(k+1)分。
二是找到i到j区间内与j点颜色相同的点t,先消除t和j之间颜色不同的区间,然后消除t,j,j后面与j颜色相同的k个点,获得(k+1)*(k+1)分。
#include<bits/stdc++.h>
using namespace std;
int n,a[210];
int dp[210][210][210];
int dfs(int l,int r,int k)
{
int i,j;
if(dp[l][r][k]!=-1)
return dp[l][r][k];
if(l>r)
return 0;
dp[l][r][k]=dfs(l,r-1,0)+(k+1)*(k+1);
for(i=r-1;i>=l;i--)
{
if(a[i]==a[r])
{
dp[l][r][k]=max(dp[l][r][k],dfs(l,i,k+1)+dfs(i+1,r-1,0));
}
}
return dp[l][r][k];
}
int main()
{
int T,cas=0;
scanf("%d",&T);
while(T--)
{
int i,j;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(dp,-1,sizeof(dp));
int ans=dfs(1,n,0);
printf("Case %d: %d\n",++cas,ans);
}
return 0;
}
2.点击打开链接
n本书,给出每本书的长和宽。将这n本书放在三层书架上,使其书架可能的最长*最宽最小。
书从高到低放,默认最高的书放在第一层架子上。
dp[i][j]第二层书宽为i第三层书宽为j的最小高度。
#include<bits/stdc++.h>
using namespace std;
struct Node
{
int h,w;
bool operator < (Node&other)const
{
return h>other.h;
}
}node[101];
int dp[3100][3100];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int i,j,k,sum=0;
for(i=0;i<n;i++)
{
scanf("%d%d",&node[i].h,&node[i].w);
sum+=node[i].w;
}
sort(node,node+n);
memset(dp,0x3f3f3f3f,sizeof(dp));
dp[0][0]=0;
for(k=1;k<n;k++)
{
for(i=sum;i>=0;i--)
{
for(j=sum;j>=0;j--)
{
if(dp[i][j]!=0x3f3f3f3f)
{
if(i==0)
dp[i+node[k].w][j]=min(dp[i+node[k].w][j],dp[i][j]+node[k].h);
else
dp[i+node[k].w][j]=min(dp[i+node[k].w][j],dp[i][j]);
if(j==0)
dp[i][j+node[k].w]=min(dp[i][j+node[k].w],dp[i][j]+node[k].h);
else
dp[i][j+node[k].w]=min(dp[i][j+node[k].w],dp[i][j]);
}
}
}
}
int ans=0x3f3f3f3f;
for(i=1;i<=sum;i++)
{
for(j=1;j<=sum;j++)
{
if(dp[i][j]!=0x3f3f3f3f)
{
int t=max(i,j);
t=max(t,sum-i-j);
ans=min(ans,(dp[i][j]+node[0].h)*t);
}
}
}
printf("%d\n",ans);
}
return 0;
}
3.点击打开链接
有趣的暴力题目,求指定区间最小的两数之差。
#include<bits/stdc++.h>
using namespace std;
const int N=10010;
const int M=200010;
int a[M],mp[N];
int solve()
{
int l,r,i,j;
scanf("%d%d",&l,&r);
memset(mp,0,sizeof(mp));
if(l-r+1>=N)
return 0;
for(i=l;i<=r;i++)
{
mp[a[i]]++;
if(mp[a[i]]>=2)
return 0;
}
int t=-N,ans=N;
for(i=1;i<=N;i++)
{
if(mp[i])
{
ans=min(ans,i-t);
t=i;
}
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,i,j,k,q;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&q);
while(q--)
{
printf("%d\n",solve());
}
}
}