名字是英文我就懒得翻译了哈
第一题
一道比较水的题目
但是我错了。。。
题目大意是有一条船,它有一定长度,将有j个苹果按顺序掉落(前面不掉完后面不接着掉),求船在指定范围内接到所有苹果最少需要移动多少格?
分析
第一题一般都是水(个屁)题
很明显这题可以膜掉模拟
设两个变量left和right,代表船的左坐标和右坐标
当苹果在船右边时,right=苹果的位置;left=right-船的长度+1
当苹果在船左边时,left=苹果的位置;right=left+船的长度-1
#include <iostream>
#include <cstdio>
int n,m,j,a[100001],i,l,r,s;
int main()
{
scanf("%d%d%d",&n,&m,&j);
l=1;r=m;
for (i=1;i<=j;i++)
{
scanf("%d",&a[i]);
if (a[i]>r)
{
s+=a[i]-r;
r=a[i];
l=a[i]-m+1;
}
else
if (a[i]<l)
{
s+=l-a[i];
l=a[i];
r=a[i]+m-1;
}
}
printf("%d",s);
}
第二题
嗯,我承认一开始没啥子思路,结果后来忽然开窍了
题目大意是把在一个大方阵里面的所有子方阵的正对角线上的和减去副对角线上的和,求出一个子方阵并使这个和最大,输出这个和
分析
这题使用前缀和做,求出正对角线的前缀和以后,又求一次副对角线的前缀和
然后就i,j枚举正方形左上角的坐标,k枚举正方形的边长(最大可以为min(n-i,n-j))
接着套前缀和常用的方法啊
大的-小的=中间的
这不就AC了么!
P.S.唯一初评AC的。。。
#include <iostream>
#include <cstdio>
using namespace std;
int a[401][401],b[401][401],s[401][401];
int i,j,k,n,m;
int main()
{
scanf("%d",&n);
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
scanf("%d",&s[i][j]);
a[i][j]=s[i][j]+a[i-1][j-1];
b[i][j]=s[i][j]+b[i-1][j+1];
}
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
for (k=1;k<=min(n-i,n-j);k++)
m=max(m,(a[i+k][j+k]-a[i-1][j-1])-(b[i+k][j]-b[i-1][j+k+1]));
printf("%d",m);
}
第三题
这题当时我看到就懵逼了
这数据!!!
题目大意是有n个男的,n个女的,有些男的喜欢跟比他矮的女生跳舞,有些男的喜欢跟比他高的女生跳舞,女生也是一样的情况。喜欢矮的用负整数来表示,喜欢高的用正整数来表示,其绝对值为他们的身高,求最多可有多少对男女达成一对?
1500<=绝对值<=2500
分析
首先这玩意儿得快排,两边都排,一边小到大,一边大到小
然后求出男女生从负整数转变到正整数的那个点(或相反)
现在假设(最好)女生小到大,男生大到小
然后i做循环,指向男生
j做循环内指针,指向女生
若女生与男生的值不匹配的话,男生的指针就会往前,因为是按顺序的,这个男生连最基本的都不能符合,那么后面的都不行,男生的指针一直往前,直到男生的值变为负数为止
若男女生的值可以相匹配,而且因为与前文相似的道理,一定是最恰当的一对,所以两个指针都往前,表示已配对
然后处理女生大到小,男生小到大的情况也反之亦然
这玩意儿很长……但是基本是快排占的空间
#include <iostream>
#include <cstdio>
using namespace std;
int n,a[100001],b[100001];
int i,j,xb,xg,s;
int abs(int x)
{
if (x<0) return -1*x;
return x;
}
void qsa(int low,int high)
{
int i=low,j=high,mid=a[(low+high)/2],t;
if (low>=high) return;
do
{
while (mid>a[i]) i++;
while (mid<a[j]) j--;
if (i<=j)
{
t=a[i];a[i]=a[j];a[j]=t;
i++;j--;
}
}
while (i<=j);
qsa(i,high);
qsa(low,j);
}
void qsb(int low,int high)
{
int i=low,j=high,mid=b[(low+high)/2],t;
if (low>=high) return;
do
{
while (mid<b[i]) i++;
while (mid>b[j]) j--;
if (i<=j)
{
t=b[i];b[i]=b[j];b[j]=t;
i++;j--;
}
}
while (i<=j);
qsb(i,high);
qsb(low,j);
}
int main()
{
scanf("%d",&n);
for (i=1;i<=n;i++)
scanf("%d",&a[i]);
for (i=1;i<=n;i++)
scanf("%d",&b[i]);
qsa(1,n);
qsb(1,n);
for (i=1;i<=n;i++)
{
if (xg==0&&a[i]>0)
xg=i;
if (xb==0&&b[i]<0)
xb=i;
}
if (xg==0) xg=n+1;
if (xb==0) xb=n+1;
j=1;
for (i=1;i<=xb-1;i++)
if (abs(a[j])>b[i])
{
if (a[j]>0) break;
j++;
s++;
}
j=xg;
for (i=xb;i<=n;i++)
if (abs(b[i])>a[j])
{
if (a[j]==0) break;
j++;
s++;
}
printf("%d",s);
}
第四题
背包吧,复杂点而已
简单来说,就是带必买部件的背包(捆绑销售。。)
分析
我已经说了是背包了!
因为有正常商品和捆绑销售附件,而且附件至多有两个,那就很好处理了。。。
只要开始的时候在主件与附件之间建立一个类似于邻接矩阵的东西就好了
然后DP时跳过处理附件,处理主件的时候分类讨论就OK了
#include <iostream>
#include <cstdio>
using namespace std;
int n,r,w[61][3],has[61],l[61][2],f[61][32001],i,j,f1,f2;
int main()
{
//freopen("budget.in","r",stdin);
//freopen("budget.out","w",stdout);
scanf("%d%d",&n,&r);
for (i=1;i<=r;i++)
{
scanf("%d%d%d",&w[i][0],&w[i][1],&w[i][2]);
w[i][1]*=w[i][0];
if (w[i][2]>0)
has[w[i][2]]++,l[w[i][2]][has[w[i][2]]]=i;
}
for (i=1;i<=r;i++)
for (j=0;j<=n;j++)
if (w[i][0]>j||w[i][2]>0)
f[i][j]=f[i-1][j];
else
{
f[i][j]=max(f[i-1][j],f[i-1][j-w[i][0]]+w[i][1]);
if (has[i]>=1)
{
f1=l[i][1];
if(j-w[i][0]-w[f1][0]>=0)f[i][j]=max(f[i][j],f[i-1][j-w[i][0]-w[f1][0]]+w[i][1]+w[f1][1]);
}
if (has[i]==2)
{
f2=l[i][2];
if (j-w[i][0]-w[f2][0]>=0)
f[i][j]=max(f[i][j],f[i-1][j-w[i][0]-w[f2][0]]+w[i][1]+w[f2][1]);
if (j-w[i][0]-w[f1][0]-w[f2][0]>=0)
f[i][j]=max(f[i][j],f[i-1][j-w[i][0]-w[f1][0]-w[f2][0]]+w[i][1]+w[f1][1]+w[f2][1]);
}
}
printf("%d",f[r][n]);
}
写于7.7 7:57