码迷,mamicode.com
首页 > 其他好文 > 详细

20190824

时间:2019-08-24 16:59:40      阅读:85      评论:0      收藏:0      [点我收藏+]

标签:现在   数字   单元格   operator   整数   目标   return   add   pac   

一.友好的生物

我去看了神仙陈启峰2016的论文

1.首先我们假设K=3,并且忽略

"但是属性K与众不同,这种属性差别越小的两种生物越友好"这一条件

那么对于任意a,b

那么 (±a.k[1]±a.k[2]±a.k[3])-(±b.k[1]±b.k[2]±b.k[3])

因为根据常理 c-d<=|c-d|

也就是说只有在符号正确的情况下,我们才能得到最大差值

在2^k的枚举下前后同号

如何优化?

假设我们从左向右依次枚举,得到当前最小值Min,那么后面减Min一定更优

2.因为属性K与众不同,这种属性差别越小的两种生物越友好

那么我们按K从小到大排序,以来保证K的属性差别越小

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i) 
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<0||c>9)if(c==-)f=1;
    x=c^48;
    while((c=getchar())>=0&&c<=9)x=x*10+(c^48);
    if(f)x=-x;
}

const int maxn=100005;

int n,m,C[6];
struct node
{
    int k[6];
    bool operator<(node b)const 
    {
        re k[m]<b.k[m];
    }
}a[maxn];


int main()
{
    
    rd(n),rd(m);
    inc(i,1,m)rd(C[i]);
    
    inc(i,1,n)
    inc(j,1,m)
    {
        rd(a[i].k[j]);
        a[i].k[j]*=C[j]; 
    }
    
    
    sort(a+1,a+n+1);
    
    int S=1<<(m-1),ans=0,Min;
    
    inc(s,0,S)
    {
        Min=10000000;
        inc(i,1,n)
        {
            int now=0;
            inc(j,1,m-1)
            if(s&(1<<(j-1)))
                now+=a[i].k[j];
            else now-=a[i].k[j];
            now-=a[i].k[m];
            ans=max(ans,now-Min);
            Min=min(Min,now);
        }
    }
    
    printf("%d",ans);
    re 0;
} 

二.基因重组

Juicepry®是一个世界著名的实验室。目前,实验室的科学家们正致力于对生物基因的重组进行深入研究。基因的物质载体是脱氧核糖核酸(DNA)。DNA是一种仅由A、T、G、C四种基元构成的双螺旋结构的有机分子。
DNA的两条单链上,同一位置的两个基元是互相对应的。A对T,G对C,因此,我们只需用任意一条链上的基元排列,就可以表示DNA的分子结构。例如:ATTGAGCCGTAT。
由于DNA微小而复杂,重组DNA极其困难,科学家们打算利用一条现成的DNA链作原材料拼接成另外一条新的DNA链。即使这样,拼接DNA仍然是一件繁重的工作,非人力所能胜任。所以科学家们制造了一种手术机器人TuringM来完成这项任务。TuringM每次只能在目标链(T)的右端与原材料 (S) 的左端进行操作。它有下列几种基本拼接操作:

对于每种操作,机器人的单位时间耗费如上表所示(单位:分钟)。最后剩余的原材料自动丢弃。
现在的任务是请你编一个程序,帮助科学家们找出完成DNA链拼接的最少时间。
可怜八月二十四,LL不会做dp

二.危险的迷宫

近来发现了一个古老的地下迷宫,已探明该迷宫是一个A行B列的矩阵,该迷宫有N个不同的出口与N个不同的入口,任一单元格不会既为入口又为出口。为了进一步探明与发掘该迷宫,N个考古队员分别从地上的N个不同的入口进入迷宫,并且计划从N个不同的出口出来。每个队员任意选择一个出口出来,但任意两名队员不会选择同一个出口。
  迷宫中的每一格与其相邻的某些格相通。该迷宫设计非常精妙,在不知道具体机关的情况下,人一旦离开其所在格后,该格将迅速关闭,且再也不能开启,也就是说每一格仅能进入一次。更糟的是,迷宫中的每一格都有一定的危险性,专家们用1至100的整数表示,数值越大表示越危险。正因为如此,再加之每一格都不很宽敞,两人一起进入比较危险,所以规定不能两个人同时进入同一格。
  为了队员们的安全着想,希望你能够编程求出如何使队员们所经过单元格的危险性总和最小。
【样例解释】
  有如下迷宫:
  每一格中的数字表示该格的危险程度。两格间若有空缺,表示这两格相通。
  入口有两个:(1,1)即第一行第一列,(1,2)即第一行第二列
  出口也有两个:(2,3)即第二行第三列,(3,4)即第三行第四列
  两名队员的最好的行动方案之一,如上图红蓝箭头所示。危险程度之和最小为235。

 

 莫说了,最小费用最大流模板

#include<bits/stdc++.h>
#define re return
#define ll long long
#define inc(i,l,r) for(int i=l;i<=r;++i)

using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<0||c>9)if(c==-)f=1;
    x=c^48;
    while((c=getchar())>=0&&c<=9)x=x*10+(c^48);
    if(f)x=-x;
}

const int maxn=305;

int n,m,K,V,s,k=1,t,C,hd[maxn];
int cur[maxn],dis[maxn],vis[maxn];

struct node{
    int to,nt,flow,cost;
}e[100000];
inline void add(int x,int y,int flow,int w)
{
    e[++k].to=y;e[k].nt=hd[x];hd[x]=k;e[k].flow=flow;e[k].cost=w;
    e[++k].to=x;e[k].nt=hd[y];hd[y]=k;e[k].flow=0;   e[k].cost=-w;
}

inline bool bfs()
{
    inc(i,1,t)
    dis[i]=214545444;
    
    dis[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        vis[u]=0;
        q.pop();
        for(int i=hd[u];i;i=e[i].nt)
        {
            int v=e[i].to;
            if(dis[v]>dis[u]+e[i].cost&&e[i].flow)
            {
                dis[v]=dis[u]+e[i].cost;
                if(!vis[v])q.push(v);
                vis[v]=1;
            }
        }
    }
    re dis[t]!=214545444;
}


inline int dfs(int u,int flow)
{
    if(u==t)
    {
        C+=flow*dis[t];
        re flow;
    }
    int delta=flow;
    for(int &i=cur[u];i;i=e[i].nt)
    {
        int v=e[i].to;
        if(dis[v]==dis[u]+e[i].cost&&e[i].flow)
        {
            int d=dfs(v,min(delta,e[i].flow));
            e[i].flow-=d;e[i^1].flow+=d;
            delta-=d;
            if(!delta)re flow; 
        }
    }
    re flow-delta;
}

int main()
{

    freopen("maze.in","r",stdin);
    freopen("maze.out","w",stdout);
    
    int x1,x2,y1,y2,x,y;
    rd(n),rd(m);
    int tot=n*m;
    s=tot+tot+1;
    t=s+1;
    inc(i,1,n)
    {
        int v=(i-1)*m;
        inc(j,1,m)
        {
            rd(x);
            add(v+j,v+j+tot,1,x);
        }
    }
    
    rd(K);
    inc(i,1,K)
    {
        rd(x1),rd(y1),rd(x2),rd(y2);
        add((x1-1)*m+y1+tot,(x2-1)*m+y2,1,0);
        add((x2-1)*m+y2+tot,(x1-1)*m+y1,1,0);
    }
    
    rd(V);
    inc(i,1,V)
    {
        rd(x),rd(y);
        add(s,(x-1)*m+y,1,0);
    }
    inc(i,1,V)
    {
        rd(x),rd(y);
        add((x-1)*m+y+tot,t,1,0);
    } 
    
    
    int ans=0;
    while(bfs())
    {
        inc(i,1,t)cur[i]=hd[i];
        ans+=dfs(s,V);
    }
    if(ans==V)
    printf("%d",C);
    else printf("-1");
    re 0;
}

 

20190824

标签:现在   数字   单元格   operator   整数   目标   return   add   pac   

原文地址:https://www.cnblogs.com/lsyyy/p/11405114.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!