关于如何用2520缩AC与数组大小怎么开
查看原帖
关于如何用2520缩AC与数组大小怎么开
490694
Compound_Interest楼主2022/4/15 11:45
#include<iostream>
#include<algorithm>
using namespace std;
int a[105],d[105],stone[350000];
int f[350000]; //压缩路径后f[]就不必开10^9那么大了 
int main()
{
    int l,s,t,m;
    cin>>l>>s>>t>>m;
    for (int i=1;i<=m;i++)
        cin>>a[i];
    sort(a+1,a+m+1); //输入石子坐标可能无序 
    for (int i=1;i<=m;i++)
        d[i]=(a[i]-a[i-1])%2520; //要对1~10的最小公倍数取余,压缩路径的核心
    for (int i=1;i<=m;i++)
    {
        a[i]=a[i-1]+d[i];
        stone[a[i]]=1; //此处有石子,标记 
    }
    l=a[m]; //压缩路径后的总长度 
    for (int i=0;i<=l+t;i++) f[i]=m; //f[i]表示到位置i最少能踩到的石子数  
    f[0]=0;
    //以上是初始化,接下来是动归
    for (int i=1;i<=l+t;i++)
        for (int j=s;j<=t;j++)
        {
            if (i-j>=0)
                f[i]=min(f[i],f[i-j]); //状态转移方程 
            f[i]+=stone[i];
        }
    int ans=m;
    for (int i=l;i<l+t;i++) ans=min(ans,f[i]);
    cout<<ans<<endl;
    return 0;
}

这篇是个人认为比较清晰的题解,可惜被这组数据HACK了

10000
8 9 2
2528 5049

应输出0,这份代码输出1

锅出在哪?

仔细观察2520缩的结果可以发现

10000
8 9 2
2528 5049

2528->8
5049->9

即缩完变成 8 9

两个原本距离很远的点被拉进了

原来可以先跳到2520

再2520+9从而跳过2528

然后如果直接2520+2529=5049显然不优

我们可以后退一个8,再跳一个9即可避开5049

即5041+9=5050

从而可以得到在距离被拉进的两个点之间的距离+t即可处理这样的错误

注意不能无脑加t拉开距离,不然会出现一些原本距离很近由于加t而产生的一些不合法的更优解

附上AC代码

#include<cstdio>
#include<algorithm> 
#include<cstring>
using namespace std;
const int maxn=2.6e5;
int a[110],dis[110],m,L,s,t;
int dp[maxn],is[maxn];
int main(){
	//freopen("P1052_1.in","r",stdin);
	//freopen("my.txt","w",stdout);
	scanf("%d%d%d%d",&L,&s,&t,&m);
	for(int i=1;i<=m;i++) scanf("%d",&a[i]);
	sort(a+1,a+1+m);
	for(int i=1;i<=m;i++){
		if(a[i]-a[i-1]>=2520) dis[i]=(a[i]-a[i-1])%2520+t;
		else dis[i]=(a[i]-a[i-1])%2520;
	}
	for(int i=1;i<=m;i++){
		a[i]=a[i-1]+dis[i];
		is[a[i]]=1;
	}
	//for(int i=1;i<=m;i++) printf("a[%d]=%d\n",i,a[i]);
	L=a[m];
	memset(dp,0x3f,sizeof(dp));
	dp[0]=0;
	for(int i=1;i<=L+t;i++)
		for(int j=s;j<=t;j++){
			if(i-j>=0) dp[i]=min(dp[i],dp[i-j]+is[i]);
		}
	int ans=dp[L];
	for(int i=L;i<L+t;i++)
		ans=min(ans,dp[i]);
	printf("%d",ans);
	return 0;
}

再说说关于数组要开多大,取一个极限

即每个石头两两相差2519且t=10

则数组大小为(2519+10)*100

开2.6e5即可

当然空间肯定够用,可以开大一点

如果我说的有错误的地方请各位神犇指正

2022/4/15 11:45
加载中...