HGOI20181031 模拟题解

sol:第一题就DP?!然后写了O(n^2) dp再考虑优化!!!(尽量部分分带上!!!)

我写了正确的dp然后优化错了,具体的dp方法是考虑到对于右侧到左侧他是没有后效性的

所以定义f[i]为i及以后最大的代价和,对于合法的j,转移f[i]=max{f[j]+P[i]},j需要满足a[i]+x[i]<a[j],j>=i

由于给出的a[i]递增然后我只要往i的右侧找到第一个合法的j然后转移就行了,复杂度O(n log n)

我错在了用堆来优化,然后把后面的删掉了,其实可以再前面的从被误删的东西转移而来。

code:

# include <bits/stdc++.h>
# ifdef O_2
# pragma GCC optimze(2)
# endif
# define int long long
using namespace std;
const int MAXN=1e5+10;
int f[MAXN],a[MAXN],x[MAXN],p[MAXN];
int n;
inline int read()
{
    int X=0,w=0;char c=0;
    while (!(c>='0'&&c<='9')) w|=c=='-',c=getchar();
    while (c>='0'&&c<='9') X=(X<<1)+(X<<3)+(c^48),c=getchar();
    return w?-X:X;
}
inline void write(int x)
{
    if (x<0) { x=-x;putchar('-');}
    if (x>9) write(x/10);
    putchar('0'+x%10);
}
inline void writeln(int x) { write(x);putchar('\n');}
signed main()
{
    n=read();
    for (int i=1;i<=n;i++) 
      a[i]=read(),p[i]=read(),x[i]=read();
    f[n]=p[n];
    for (int i=n-1;i>=1;i--) {
        f[i]=f[i+1];
        int j=upper_bound(a+i+1,a+1+n,a[i]+x[i])-a;
        f[i]=max(max(f[i],p[i]),f[j]+p[i]);
    }  
    writeln(f[1]);
    return 0;
 }

 

sol:这道题目对于100%的数据n,m<=3000,显然发现这一定是O(n2)的算法,

然后如果对于X1到X2的最短路径设为R1,X3到X4最短路劲R2,要求R1和R2交的尽可能多,那么这个解一定更优

首先一定要在最短路上,其次要求R1和R2尽可能交的更多,我们不妨设刚开始交的地方设为i,交结束的地方设为j

我们先求出X1,X2,X3,X4到各点的最短路D1,D2,D3,D4

我们枚举i然后再枚举j 由上图可以看出就是D1[i]+D2[j]+D3[i]+D4[j]+dist(i,j)在枚举j之前我们可以O(n)求出i的最短路D5

那么就是最小化D1[i]+D2[j]+D3[i]+D4[j]+D5[j],

然后我们交换(X1,X2)or (X3,X4) 之中的任意一对然后再求min,就是D1[i]+D2[j]+D3[j]+D4[i]+D5[j],

然后对于每一次枚举Ans=Min(D1[i]+D2[j]+D3[i]+D4[j]+D5[j],D1[i]+D2[j]+D3[j]+D4[i]+D5[j],ans)

对于一个显然的情况我们最后特判就是直接 X1走到X2,X3 走到 X4 最短路虽然并没有重复的路 即 ans=Min(ans,D1[X2]+D3[X4]);

code:

# include <bits/stdc++.h>
# ifdef O_2
# pragma GCC optimze(2)
# endif
using namespace std;
const int MAXN=3005;
int n,m,X1,X2,X3,X4;
int D1[MAXN],D2[MAXN],D3[MAXN],D4[MAXN],D5[MAXN];
int tot=0,head[MAXN];
bool vis[MAXN];
struct rec{ int pre,to,w;}a[MAXN*2];
inline int read()
{
    int X=0,w=0;char c=0;
    while (!(c>='0'&&c<='9')) w|=c=='-',c=getchar();
    while (c>='0'&&c<='9') X=(X<<1)+(X<<3)+(c^48),c=getchar();
    return w?-X:X;
}
inline void write(int x)
{
    if (x<0) { x=-x;putchar('-');}
    if (x>9) write(x/10);
    putchar('0'+x%10);
}
inline void writeln(int x) { write(x);putchar('\n');}
void adde(int u,int v,int w)
{
    a[++tot].pre=head[u];
    a[tot].to=v;
    a[tot].w=w;
    head[u]=tot;
}
struct node{ int id,dist;};
int d[MAXN];
queue<node>q;
void bfs(int s)
{
    memset(vis,false,sizeof(vis));
    memset(d,0x3f,sizeof(d));
    d[s]=0; vis[s]=1;
    q.push((node){s,0});
    while (!q.empty()) {
        node u=q.front();q.pop();
        for (int i=head[u.id];i;i=a[i].pre) {
            int v=a[i].to;
            if (vis[v]) continue;
            vis[v]=1;
            d[v]=u.dist+1;
            q.push((node){v,d[v]});
        }
    } 
}
int Min(int a,int b,int c)
{
    if (b<a) a=b;
    if (c<a) a=c;
    return a;
}
int main()
{
    n=read();m=read();
    X1=read();X2=read();X3=read();X4=read();
    int u,v;
    for (int i=1;i<=m;i++) {
        u=read();v=read();
        adde(u,v,1); adde(v,u,1);
    }
    bfs(X1); memcpy(D1,d,sizeof(d));
    bfs(X2); memcpy(D2,d,sizeof(d));
    bfs(X3); memcpy(D3,d,sizeof(d));
    bfs(X4); memcpy(D4,d,sizeof(d));
    int ans=m;
    for (int i=1;i<=n;i++) {
        bfs(i); memcpy(D5,d,sizeof(d));
    for (int j=1;j<=n;j++) 
      ans=Min(ans,D1[i]+D3[i]+D2[j]+D4[j]+D5[j],D1[i]+D4[i]+D3[j]+D2[j]+D5[j]);
    }
    ans=min(ans,D1[X2]+D3[X4]);
    writeln(ans);
    return 0;
 }

猜你喜欢

转载自www.cnblogs.com/ljc20020730/p/9882489.html
今日推荐