关于2024-4-15拼多多笔试
被A弄的有点红温了,这次题解就随便写写吧
A
一眼DP 因为最多挖掉两个空格 但是只有64分
调了快一小时的DP都没出答案,有人和我说,只考虑挖第一个或最后一个,或者挖前两个,最后两个,挖最前最后过了?????
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define _for(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using namespace std;
char s[10050];
long long dp[10050][3];
void solve(int n)
{
scanf("%s",s+1);
if(n<3)
{
printf("0 0\n");
return;
}
int len=strlen(s+1);
len=n;
for(int i=0;i<=n+5;i++)
{
_for(j,0,2)
{
dp[i][j]=1000000000;
}
}
dp[0][0]=0;
_for(i,1,len)
{
_for(j,1,2) dp[i][j]=dp[i-1][j-1];
if(i>=3)
{
dp[i][0]=dp[i-3][0]+abs((int)s[i-2]-'P')+abs((int)s[i-1]-'D')+abs((int)s[i]-'D');
_for(j,1,2)
{
dp[i][j]=min(dp[i][j],dp[i-3][j]+abs((int)s[i-2]-'P')+abs((int)s[i-1]-'D')+abs((int)s[i]-'D'));
}
}
}
printf("%d %lld\n",len/3,dp[len][len%3]);
}
int main(void)
{
int n;
while(scanf("%d",&n)!=EOF)
{
solve(n);
}
}
/*
6
ADDPBB
6
ADDPBB
7
ABCDEFG
7
ABCDEFG
7
ABCDEFG
6
ADDPBB
7
ABCDEFG
*/
B
由于当(a[i]==a[i+1])时,合法区间的左端点一定≥l,因此一边维护目前所有合法区间的和,一边加给更新答案即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define _for(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using namespace std;
#define MAXN 1000050
const int mod=10000007;
int arr[MAXN];
int main(void)
{
int n;
scanf("%d",&n);
int ans=0;
int cnt=0;
int flag=0;
_for(i,1,n) scanf("%d",&arr[i]);
_for(i,1,n)
{
if(i==1||arr[i]==arr[i-1])
{
cnt=0;
flag=0;
}
else
{
++flag;
cnt=(cnt)+(1ll*arr[i]*flag%mod)+arr[i-1];
cnt%=mod;
ans+=cnt;
ans%=mod;
}
// printf("%d %d\n",cnt,ans);
}
printf("%d",ans);
}
C
枚举第一段,计算答案并且维护即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define _for(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define MAXN 1050
#define pii pair<int,int>
int n;
int arr[MAXN];
pii judge(int len)
{
int req=0;
int wid=len;
_for(i,1,len)
{
req+=arr[i];
}
int need,cnt;
need=req,cnt=0;
_for(i,len+1,n)
{
need-=arr[i];
++cnt;
if(need<0)
{
return pii(n+1,-1);
}
if(need==0)
{
need=req;
wid=max(wid,cnt);
cnt=0;
}
}
if(need!=req)
{
return pii(n+1,-1);
}
return pii(wid,req);
}
int main(void)
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
_for(i,1,n) scanf("%d",&arr[i]);
pii ans=pii(n+1,-1);
_for(i,1,n)
{
ans=min(ans,judge(i));
}
printf("%d %d\n",ans.first,ans.second);
}
}
D
做了个猜测,掰掉的巧克力要么取其中一块分,要么取其中一块的全部,用另一块分,由于时间紧张,没有去做数学证明,但是感觉比较合理,然后进行O(n^4)的DP即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define _for(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define MAXN 55
int dp[MAXN][MAXN][MAXN];
void solve(int n,int m,int k)
{
// printf("solve(%d %d %d)\n",n,m,k);
dp[n][m][k]=998244353;
if(n*m==k||k==0)
{
dp[n][m][k]=0;
return;
}
if(n==0||m==0)
{
dp[n][m][k]=-1;
return;
}
int cost;
for(int i=1;i<n;i++)
{
cost=m*m;
if(dp[n-i][m][k]!=-1) dp[n][m][k]=min(dp[n][m][k],dp[n-i][m][k]+cost);
if(k-m*i>=0&&dp[n-i][m][k-m*i]!=-1) dp[n][m][k]=min(dp[n][m][k],dp[n-i][m][k-m*i]+cost);
// printf("%d of n: %d\n",i,dp[n][m][k]);
}
for(int i=1;i<m;i++)
{
cost=n*n;
if(dp[n][m-i][k]!=-1) dp[n][m][k]=min(dp[n][m][k],dp[n][m-i][k]+cost);
if(k-n*i>=0&&dp[n][m-i][k-n*i]!=-1) dp[n][m][k]=min(dp[n][m][k],dp[n][m-i][k-n*i]+cost);
// printf("%d of m: %d\n",i,dp[n][m][k]);
}
if(dp[n][m][k]==998244353) dp[n][m][k]=-1;
}
int main(void)
{
_for(i,0,50) _for(j,0,50) _for(k,0,50) solve(i,j,k);
int T;
scanf("%d",&T);
while(T--)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
printf("%d\n",dp[x][y][z]);
}
}
查看18道真题和解析

巨人网络公司福利 91人发布