其他分享
首页 > 其他分享> > 这次应该叫高二上几调?

这次应该叫高二上几调?

作者:互联网

B. biology

错误思路:按a的值分个层,直接把每层的最大值的点编号放到队列里,后来忽然发现每个a最小一层的点都有可能当一次起点,它的位置决定了后面的点的位置,不能单独考虑起点b值的大小,于是就让每一个最小的a当一次起点循环一遍。我已经做好了它超时的心理准备,但是有WA的点就不太理解。。。如果有读者能指出错因我会很感谢的。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 4e6 + 3;
const int N = 1e7 + 2;
const ll INF = 1e17;

int n, m, q[maxn], l=1, r, num, pos, hv[maxn], cnt;
ll ans;
struct node
{
    int x, y, a, b;
    bool operator < (const node &T)
    {
        return a < T.a;
    }
}p[maxn];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int main()
{
    n = read(); m = read();
    //printf("n=%d m=%d\n", n, m);
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m ;j++)
        {
            p[++num].a = read();
            //printf("p[%d].a = %d\n", num, p[num].a);
            p[num].x = i; p[num].y = j;
        }
    }
    num = 0;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            p[++num].b = read();
        }
    }
    sort(p+1, p+1+num);
    //printf("%d", p[1].a);
    for(int i=1; i<=num; i++)
    {
        if(p[i].a)
        {
            pos = i; break;
        }
    }
    q[++r] = pos;
    hv[++cnt] = pos;
    for(int i=pos+1; i<=num; i++)
    {
        //printf("p[%d].a = %d\n", i, p[i].a);
        //printf("cmp : %d %d\n", p[i].a, p[q[1]].a);
        if(p[i].a == p[q[1]].a) 
        {
            hv[++cnt] = i;
            pos = i;
        }
        else break;
    }
    //printf("cnt=%d\n", cnt);
    for(int k=1; k<=cnt; k++)
    {
        ll sum = 0;
        l = 1, r = 0;
        q[++r] = hv[k];
        for(int i=pos+1; i<=num; i++)
        {
            if(p[i].a > p[q[r]].a) q[++r] = i;
            else if(p[i].a == p[q[r]].a)
            {
                if(r == 1)
                {
                    continue;
                }
                else if((ll)p[i].b+abs(p[i].x-p[q[r-1]].x)+abs(p[i].y-p[q[r-1]].y) > (ll)p[q[r]].b+abs(p[q[r]].x-p[q[r-1]].x)+abs(p[q[r]].y-p[q[r-1]].y))
                {
                    q[r] = i;
                }
            }
        }
        sum += p[q[1]].b;
        for(int i=2; i<=r; i++)
        {
            sum += (ll)p[q[i]].b+abs(p[q[i]].x-p[q[i-1]].x)+abs(p[q[i]].y-p[q[i-1]].y);
        }
        //printf("sum=%lld\n", sum);
        ans = max(ans, sum);
    }
    /*for(int i=pos+1; i<=num; i++)
    {
        if(p[i].a > p[q[r]].a) q[++r] = i;
        else if(p[i].a == p[q[r]].a)
        {
            if(r == 1)
            {
                if(p[i].b > p[q[r]].b) q[r] = i;
            }
            else if((ll)p[i].b+abs(p[i].x-p[q[r-1]].x)+abs(p[i].y-p[q[r-1]].y) > (ll)p[q[r]].b+abs(p[q[r]].x-p[q[r-1]].x)+abs(p[q[r]].y-p[q[r-1]].y))
            {
                q[r] = i;
            }
        }
    }*/
    /*ans += p[q[1]].b;
    for(int i=2; i<=r; i++)
    {
        ans += (ll)p[q[i]].b+abs(p[q[i]].x-p[q[i-1]].x)+abs(p[q[i]].y-p[q[i-1]].y);
    }*/
    printf("%lld", ans);

    return 0;
}
只有30分

然后就是题解了:

第一步还是分层,但这个分层是放到数组里,而不是在脑海中。预处理的标准是每一个层号都能找到这一层的数值,而每一层的数值也能对应回层的编号。

dp[i][j] 表示当前路径的结尾在(i, j)位置的最大吸引度之和。 f[i][j] = max{f[i'][j'] + b[i'][j'] + ∣i − i ∣ + ∣j − j ∣, a[i][j] = a[i'][j'] + x, x>=1} 。

把绝对值拆开:f[i][j]可能为f[i'][j']+b[i'][j']-i'-j'+i+j或f[i'][j']+b[i'][j']+i'+j'-i-j或f[i'][j']-i'+j'+i-j或f[i'][j']+i'-j'+i+j。所以坐标转换,把(i+j, i-j)放进a[i][j]属于的分层,再用四个变量维护一下i'和j'的四种对应情况随递推的变化,递推时对应决定了当前的i和j应该加还是应该减。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2e3 + 2;
const int N = 4e6 + 3;
const ll INF = 1e17;

int a[maxn][maxn], b[maxn][maxn], n, m;
int rec[N], pos[N], cnt;
ll dp[maxn][maxn], ans, maxx[5];
bool vis[N];
vector<pair<int, int> > v[N];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int main()
{
    n = read(); m = read();
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            a[i][j] = read();
            if(!a[i][j]) continue;
            if(!vis[a[i][j]]) rec[++cnt] = a[i][j];
            vis[a[i][j]] = 1;
        }
    }
    sort(rec+1, rec+1+cnt);
    for(int i=1; i<=cnt; i++) pos[rec[i]] = i;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            b[i][j] = read();
        }
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            if(!a[i][j]) continue;
            v[pos[a[i][j]]].push_back(make_pair(i+j, i-j));
        }
    }
    for(int i=0; i<(int)v[1].size(); i++)
    {
        ll p = v[1][i].first, q = v[1][i].second;
        ll valb = b[(p+q)>>1][(p-q)>>1];//用原坐标的b值
        maxx[1] = max(maxx[1], valb-p);
        maxx[2] = max(maxx[2], valb+p);
        maxx[3] = max(maxx[3], valb-q);
        maxx[4] = max(maxx[4], valb+q);
    }
    for(int i=2; i<=cnt; i++)
    {
        for(int j=0; j<(int)v[i].size(); j++)
        {
            ll p = v[i][j].first, q = v[i][j].second;
            ll valb = b[(p+q)>>1][(p-q)>>1];
            //b'-i'-j'+b+i+j
            //b'+i'+j'+b-i-j
            //b'-i'+j'+b+i-j
            //b'+i'-j'+b-i+j
            dp[(p+q)>>1][(p-q)>>1] = max(max(maxx[1]+valb+((p+q)>>1)+((p-q)>>1),
                                             maxx[2]+valb-((p+q)>>1)-((p-q)>>1)),
                                         max(maxx[3]+valb+((p+q)>>1)-((p-q)>>1),
                                             maxx[4]+valb-((p+q)>>1)+((p-q)>>1)));
        }
        for(int j=0; j<(int)v[i].size(); j++)
        {
            ll p = v[i][j].first, q = v[i][j].second;
            ll valdp = dp[(p+q)>>1][(p-q)>>1];
            maxx[1] = max(maxx[1], valdp-p);//b-i-j
            maxx[2] = max(maxx[2], valdp+p);
            maxx[3] = max(maxx[3], valdp-q);
            maxx[4] = max(maxx[4], valdp+q);
        }
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            ans = max(ans, dp[i][j]);
        }
    }
    printf("%lld\n", ans);

    return 0;
}
感谢WR大佬

 

标签:几调,maxx,ch,高二上,这次,max,ll,int,maxn
来源: https://www.cnblogs.com/Catherine2006/p/16479034.html