• CCF201809-4 再卖菜


    问题描述:

    AC代码:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<map>
     5 #include<set>
     6 #include<vector>
     7 #include<algorithm>
     8 #include<cmath>
     9 #include<fstream>
    10 #include<iomanip>
    11 #include<queue>
    12 #include<unordered_set>
    13 using namespace std;
    14 typedef long long ll;
    15 typedef unsigned long long ull; 
    16 const ll maxn = 300 + 5;
    17 int target;
    18 
    19 int num = 1;
    20 
    21 int a[maxn], b[maxn];
    22 bool f[maxn][maxn][maxn];
    23 
    24 void dfs(int n, int x, int y){
    25     if(f[n][x][y])return;
    26     f[n][x][y] = true;
    27     if(n == target - 1){
    28         for(int i = 0; i <= 2; i++){
    29             if((3 * a[n] - b[n - 1] + i) / 2 == a[n + 1]){//原等式 应为 2 * a[n + 1] (+1) = 3 * a[n] - b[n - 1](+1) (+2)  其中括号为可选项,代码里左边等式的 +1 消失了是因为有 /2 的存在。 
    30                 b[n + 1] = 3 * a[n] - b[n - 1] - b[n] + i;
    31                 for(int i = 1; i <= target; i++){
    32                     cout << b[i] << " ";
    33                 }
    34                 exit(0);
    35             }
    36         }
    37     }
    38     for(int i = 0; i < 3; i++){
    39         b[n + 1] = 3 * a[n] - b[n] - b[n - 1] + i;
    40         if(b[n + 1] >= 1)dfs(n + 1, y, b[n + 1]);
    41     }
    42     return;
    43 }
    44 
    45 
    46 int main(){
    47 //    ios::sync_with_stdio(false);
    48 //    ifstream cin("data.txt");
    49 //    freopen("data.txt", "r", stdin);
    50     memset(f, false, sizeof(f));
    51     int n;
    52     cin >> n;
    53     target = n;
    54     for(int i = 1; i <= n; i++){
    55         cin >> a[i];
    56     }
    57     for(int i = 1; i <= 2 * a[1]; i++){
    58         b[1] = i;
    59         if(i != 2 * a[1]){
    60             b[2] = 2 * a[1] - i;
    61             dfs(2, b[1], b[2]);
    62         }
    63         b[2] = 2 * a[i] - i + 1;
    64         dfs(2, b[1], b[2]);
    65     }
    66     return 0;
    67 }

    我想说的:

       很菜很菜的我在绝望搜题解之前是懵逼的,搜了几篇题解都是 差分约束 的解法,然而,看到了这篇博客  https://blog.csdn.net/imotolove/article/details/82777819 ,让我眼前一亮!对啊,可以暴力的啊!

       我们的思路就是:

       假设 b[] 为所求 a[] 为已知。
       我们把不等式写出来可以得到递推式:3 * a[n] <= b[n + 1] + b[n - 1] + b[n] <= 3 * a[n] + 2
       即, 我们知道 b[n - 1]、 b[n] 时 只需枚举 0, 1, 2即可得到 b[n + 1]
       对于起始和结束的特殊情况, 改写上式。

       对于起始的 b[1] 和 b[2], 我们知道 2 * a[1] <= b[1] + b[2] <= 2 * a[1] + 1
       即我们只需从 1 到 2 * a[1]枚举 b[1] 即可确定 两个初值
       对于最后的值 b[target] , 我们需保证 同时 满足 两个式子 才能 确定最后一个值

       对于 dfs的有效性:
       我们按递推式去推 b[],若可以推出来,则一定符合题意(因为递推式是满足题意的),
       否则,中间某值出现小于 1 的情况 或者 最后的值不符合两个不等式,都会记忆下然后退出来。
       每次碰到之前记忆过得情况时,直接退出, 因为之前通过这条路走不通没必要浪费时间。

       对于字典序的解释:
       我们是依次从小到大从前往后搜的,所以第一次满足题意的解 也 一定满足了字典序最小的要求。

       最后再鸣谢一下这位CSDN博主给我的启发:

            

  • 相关阅读:
    Collections集合工具类排序
    集合的学习
    gitee使用方法
    vue 首屏优化
    vue 配置多个路由别名
    vue中的状态管理Vuex
    【Python】Pandas合并表格之(append, join , concat方法)
    elementui中提交表单自动刷新页面的问题
    滴滴实习面试题
    CSS 日常积累
  • 原文地址:https://www.cnblogs.com/peichaoL/p/10467602.html
Copyright © 2020-2023  润新知