假做法求hack或证明正确性
查看原帖
假做法求hack或证明正确性
566396
Magic_World楼主2022/9/16 10:00

我的思路是从人站着的起始点开始向左向右扩展 llrr
但我的实现方式是固定其中一个端点在外层循环,另一个在内层循环:

for(int l=c;l;l--)
for(int r=c;r<=n;r++)

这样显然可能有状态没转移到,所以我改变l,r内外层循环顺序 dp 了三遍结果就 AC 了,然而我又尝试只 dp 一次看看会怎么 WA,结果又 A 了。
同机房看了我的做法都觉得假,但我觉得即使数据水,三遍 dp 也是能转移所有状态的吧。

#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;++i)
using namespace std;

const int N = 53;
int f[N][N][2],n,c,dis[N],w[N],sum[N];
int P(int l,int r){return sum[n]-sum[r]+sum[l-1];}

int main()
{
    ios::sync_with_stdio(0);
    //freopen("data.in","r",stdin);
    memset(f,0x3f,sizeof(f));
    cin>>n>>c;
    rep(i,1,n) cin>>dis[i]>>w[i],sum[i] = sum[i-1] + w[i];
    f[c][c][1] = f[c][c][0] = 0;
    for(int l=c,tmp;l;l--)
    {
        for(int r=c;r<=n;r++)jj
        {
            tmp = P(l,r);
            f[l-1][r][0] = min(f[l][r][1]+tmp*(dis[r]-dis[l-1]),f[l][r][0]+tmp*(dis[l]-dis[l-1]));
            f[l][r+1][1] = min(f[l][r][1]+tmp*(dis[r+1]-dis[r]),f[l][r][0]+tmp*(dis[r+1]-dis[l]));
        }
    }
    for(int r=c,tmp;r<=n;r++)
    {
        for(int l=c;l;l--)
        {
            tmp = P(l,r);
            f[l-1][r][0] = min(f[l][r][1]+tmp*(dis[r]-dis[l-1]),f[l][r][0]+tmp*(dis[l]-dis[l-1]));
            f[l][r+1][1] = min(f[l][r][1]+tmp*(dis[r+1]-dis[r]),f[l][r][0]+tmp*(dis[r+1]-dis[l]));
        }
    }
    for(int l=c,tmp;l;l--)
    {
        for(int r=c;r<=n;r++)
        {
            tmp = P(l,r);
            f[l-1][r][0] = min(f[l][r][1]+tmp*(dis[r]-dis[l-1]),f[l][r][0]+tmp*(dis[l]-dis[l-1]));
            f[l][r+1][1] = min(f[l][r][1]+tmp*(dis[r+1]-dis[r]),f[l][r][0]+tmp*(dis[r+1]-dis[l]));
        }
    }
    cout<<min(f[1][n][0],f[1][n][1]);
    return 0;
}
2022/9/16 10:00
加载中...