CCF-CSP题解 201809-4 再卖菜

碎碎念。。近视加老花,还以为第二天除了第二家范围在100以内别的都不确定,于是x**算的记搜复杂度超时了。还鼓捣着什么差分区间最长路,虽然有大神用差分区间做出来了,然而自己并没有看懂。

其实就是一个记忆化搜索。搜索时用vis[n][300][300]记录访问状态。第二、三维数组下标映射第一天n-1、n号店的价格。每个数的范围是1-300,所以复杂度是n*300*300并不会超时。

注意第一天是两个数的均值,验证第n天时也是两个数的均值。

#include <bits/stdc++.h>
const int maxn = 300;

using namespace std;

int n;
int average[maxn+10];
int origin[maxn+10];

int vis[maxn+10][305][305];

bool dfs(int x)
{
    // printf("%d %d %d
", x, origin[x-1], origin[x]);
    vis[x][origin[x-1]][origin[x]] = 1;
    if (x < n)
    {
        origin[x+1] = average[x] * 3 - origin[x] - origin[x-1];
        if (origin[x+1] >= 1 && !vis[x+1][origin[x]][origin[x+1]] && dfs(x + 1))
            return true;
        origin[x+1] = average[x] * 3 + 1 - origin[x] - origin[x-1];
        if (origin[x+1] >= 1 && !vis[x+1][origin[x]][origin[x+1]] && dfs(x + 1))
            return true;
        origin[x+1] = average[x] * 3 + 2 - origin[x] - origin[x-1];
        return origin[x+1] >= 1 && !vis[x+1][origin[x]][origin[x+1]] && dfs(x + 1);
    }
    else
    {
        return (origin[x-1] + origin[x]) / 2 == average[x];
    }
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", average + i);

    for (origin[1] = 1; ; origin[1] ++)
    {
        origin[2] = average[1] * 2 - origin[1];
        if (origin[2] >= 1 && dfs(2))
            break;
        origin[2] = average[1] * 2 + 1 - origin[1];
        if (origin[2] >= 1 && dfs(2))
            break;
    }

    for (int i = 1; i <= n; i++)
    {
        printf("%d", origin[i]);
        if (i == n)
            printf("
");
        else
            printf(" ");
    }

    return 0;
}
原文地址:https://www.cnblogs.com/acboyty/p/11363140.html