zoukankan      html  css  js  c++  java
  • [csp-201809-4]再卖菜 差分约束or记忆化搜索

    先更新第一个做法:差分约束

    转化成最长路,求出的每一个解是满足差分方程的最小值

    spfa求最短路

    对于边(x->y) 有:

     1 if(dis[y] > dis[x] + a[i].d) dis[y]=dis[x]+a[i].d; 

    dis[y]的初始值为INF,dis[y]会是满足所有约束条件之中所有可能的值之中最大的(更新到最大的就不会再更新了)。

    贴一个简略的证明:

     同理,最长路求出来的是所有可能解之中最大的。

    这题是字典序最小,那么我们要转化成最长路来求,求到的每个s[i]都是可能的值中最小的一个。注意,菜价要是正整数(>=1)。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int N=3100;
     5 struct node{
     6     int x,y,d,next;
     7 }a[2*N];
     8 int n,al,first[N],b[N],s[N];
     9 bool vis[N];
    10 queue<int> q;
    11 
    12 void ins(int x,int y,int d)
    13 {
    14     al++;
    15     a[al].x=x;a[al].y=y;a[al].d=d;
    16     a[al].next=first[x];first[x]=al;
    17 }
    18 
    19 void build_edge()
    20 {
    21     al=0;
    22     memset(first,0,sizeof(first));
    23     ins(0,2,2*b[1]);
    24     ins(2,0,-(2*b[1]+1));
    25     for(int i=2;i<=n-1;i++)
    26     {
    27         ins(i-2,i+1,3*b[i]);
    28         ins(i+1,i-2,-(3*b[i]+2));
    29     }
    30     ins(n-2,n,2*b[n]);
    31     ins(n,n-2,-(2*b[n]+1));
    32     for(int i=1;i<=n;i++) ins(i-1,i,1);
    33 }
    34 
    35 void spfa()
    36 {
    37     while(!q.empty()) q.pop();
    38     memset(s,0,sizeof(s));
    39     memset(vis,0,sizeof(vis));
    40     s[0]=0;vis[0]=1;q.push(0);
    41     while(!q.empty())
    42     {
    43         int x=q.front();q.pop();
    44         for(int i=first[x];i;i=a[i].next)
    45         {
    46             int y=a[i].y;
    47             if(s[y]<s[x]+a[i].d)
    48             {
    49                 s[y]=s[x]+a[i].d;
    50                 if(!vis[y])
    51                 {
    52                     vis[y]=1;
    53                     q.push(y);
    54                 }
    55             }
    56         }
    57         vis[x]=0;
    58     }
    59 }
    60 
    61 int main()
    62 {
    63     //freopen("a.in","r",stdin);
    64     scanf("%d",&n);
    65     for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    66     build_edge();
    67     spfa();
    68     for(int i=1;i<=n;i++)
    69         printf("%d ",s[i]-s[i-1]);printf("
    ");
    70     return 0;
    71 }
  • 相关阅读:
    c++ 队列
    17:特殊类成员:函数指针5
    c++ deque 双端队列
    18:字符串-char型字符串
    c++ 16 this 和 继承 及继承机制中的构造函数 与 析构函数
    c++ string char* const char*
    c++ 小片段
    google protobuf 使用示例
    hibernate-cache
    hibernate-criteria查询(二)
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/10077196.html
Copyright © 2011-2022 走看看