【比赛】高一高考集训总结赛
一场比赛四道 DP
乐了
集训全学 DP 你还真给我全考 DP 啊
T1 乌龟棋 70 Pts
题面
设
但赛时先开了个五维 DP 数组,然后发现开不下;
正常人到这就会想到要压掉一位了,但我直接用 滚动数组 强行开下了。
然后就
点击查看代码
#include<bits/stdc++.h>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=355;
int f[45][45][45][45];
int n,m,x;
int a[N],c[10];
inline int read(){
int x=0;
char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x;
}
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
n=read();m=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=m;i++)c[read()]++;
f[0][0][0][0]=a[1];
for(int i1=0;i1<=c[1];i1++){
for(int i2=0;i2<=c[2];i2++){
for(int i3=0;i3<=c[3];i3++){
for(int i4=0;i4<=c[4];i4++){
int now=1+i1+i2*2+i3*3+i4*4;
int &v=f[i1][i2][i3][i4];
if(i1!=0)v=max(v,f[i1-1][i2][i3][i4]+a[now]);
if(i2!=0)v=max(v,f[i1][i2-1][i3][i4]+a[now]);
if(i3!=0)v=max(v,f[i1][i2][i3-1][i4]+a[now]);
if(i4!=0)v=max(v,f[i1][i2][i3][i4-1]+a[now]);
}
}
}
}
cout<<f[c[1]][c[2]][c[3]][c[4]];
return 0;
}
T2 划分大理石 100Pts
题面
多重背包,二进制拆分。
数据过水导致很多乱搞做法可以通过。
赛后这题被加了
组测试数据。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=20005;
int a[7],sum;
int w[N],f[N],cnt;
int main(){
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
while(1){
scanf("%d%d%d%d%d%d",&a[1],&a[2],&a[3],&a[4],&a[5],&a[6]);
sum=a[1]+a[2]*2+a[3]*3+a[4]*4+a[5]*5+a[6]*6;
if(!sum)break;
if((sum&1)){
puts("Can't");
continue;
}
sum/=2;
f[0]=1;
for(int i=1;i<=6;i++){
int tmp=a[i],j=1;
while(tmp>j){
tmp-=j;
w[++cnt]=j*i;
j<<=1;
}
if(tmp)w[++cnt]=tmp;
}
for(int i=1;i<=cnt;i++){
for(int j=sum;j>=w[i];j--){
f[j]=(f[j]||f[j-w[i]]);
}
}
if(f[sum])puts("Can");
else puts("Can't");
}
return 0;
}
T3 干草堆 47Pts
题面
神仙斜率优化 DP,反正我没想出来。
倒序输入和处理,设
其中
由于数据过水,这个
但我们可以使用单调栈维护这个式子,将复杂度降至
赛时先打了贪心做法,小样例直接过,大样例直接死,发现贪心假了;
然后死活想不出来 DP 状态怎么设计,然后测试点分治 贪心 + 爆搜;
然后分治出了点小锅,T 了一个点 ,
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int f[N],w[N],sum[N],g[N];
int n;
int q[N],l=1,r=0;
int main(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
cin>>n;
for(int i=n;i;i--){
cin>>w[i];
}
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+w[i];
}
q[++r]=0;
for(int i=1;i<=n;i++){
while(l<r&&sum[q[l+1]]+g[q[l+1]]<=sum[i])l++;
f[i]=f[q[l]]+1;
g[i]=sum[i]-sum[q[l]];
while(l<r&&sum[q[r]]+g[q[r]]>=sum[i]+g[i])r--;
q[++r]=i;
}
cout<<f[n];
return 0;
}
T4 围栏障碍训练场 100Pts
题面
数据结构优化 DP。
设
设
其中,
然后数据水了,
但是这题
所以没补正解。正解转自涛哥。
#include<bits/stdc++.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(a) ((a)>0?(a):(-(a)))
using namespace std;
typedef long long ll;
const int N=3e4+5;
int f[N][2],n,s;
int l[N],r[N];
int ans=INT_MAX;
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d%d",&n,&s);
for(int i=n;i;i--)scanf("%d%d",&l[i],&r[i]);
memset(f,0x3f,sizeof(f));
f[1][0]=s-l[1],f[1][1]=r[1]-s;
for(int i=1;i<=n;i++){
if(f[i][0]==0x3f3f3f3f&&f[i][1]==0x3f3f3f3f)continue;
int a=l[i],b=r[i];
bool fa=0,fb=0;
for(int j=i+1;j<=n;j++){
if(fa==1&&fb==1)break;
if(l[j]<a&&a<r[j]&&(!fa)){
f[j][0]=min(f[j][0],f[i][0]+a-l[j]);
f[j][1]=min(f[j][1],f[i][0]+r[j]-a);
fa=1;
}
if(l[j]<b&&b<r[j]&&(!fb)){
f[j][0]=min(f[j][0],f[i][1]+b-l[j]);
f[j][1]=min(f[j][1],f[i][1]+r[j]-b);
fb=1;
}
}
if(!fa)ans=min(ans,f[i][0]+abs(a));
if(!fb)ans=min(ans,f[i][1]+abs(b));
}
printf("%d",ans);
return 0;
}
正解
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,s,a[N],b[N],res[N][2];
int t[N<<3];
inline void pushdown(int x)
{
if(t[x])
{
t[x<<1]=t[x<<1|1]=t[x];
t[x]=0;
}
return ;
}
inline void change(int x,int l,int r,int ql,int qr,int q)
{
if(ql<=l&&r<=qr)
{
t[x]=q;
return ;
}
pushdown(x);
int mid=l+r>>1;
if(ql<=mid)
change(x<<1,l,mid,ql,qr,q);
if(qr>mid)
change(x<<1|1,mid+1,r,ql,qr,q);
return ;
}
inline int query(int x,int l,int r,int q)
{
if(l==r)
return t[x];
pushdown(x);
int mid=l+r>>1;
if(q<=mid)
return query(x<<1,l,mid,q);
return query(x<<1|1,mid+1,r,q);
}
int main()
{
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
cin>>n>>s;
for(int i=1;i<=n;i++)
cin>>a[i]>>b[i];
for(int i=1,q;i<=n;i++)
{
q=query(1,-N,N,a[i]);
res[i][0]=min(res[q][0]+abs(a[i]-a[q]),res[q][1]+abs(b[q]-a[i]));
q=query(1,-N,N,b[i]);
res[i][1]=min(res[q][0]+abs(b[i]-a[q]),res[q][1]+abs(b[q]-b[i]));
change(1,-N,N,a[i],b[i],i);
}
cout<<min(res[n][0]+abs(a[n]-s),res[n][1]+abs(b[n]-s));
return 0;
}
后记
-
很水的一场比赛,但是是数据水。
-
T2 没说多测组数,然后 wwppcc 和 GGrun 放了个大点上去把除了单调队列优化 DP 外的所有做法全部卡 T 了。
-
赛时 Qyun 和 HDK 的电脑炸掉了,但 Qyun 顶着这个 Debuff 砍了 190Pts,%
-
总结:题和题目排版总有一个是史。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探