zoukankan      html  css  js  c++  java
  • [补档]happiness

    happiness

    题目

    高一一班的座位表是个n×m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。

    INPUT

    第一行两个正整数n,m。
    接下来是六个矩阵
    第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值。
    第二个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择理科获得的喜悦值。
    第三个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择文科获得的额外喜悦值。
    第四个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择理科获得的额外喜悦值。
    第五个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择文科获得的额外喜悦值。
    第六个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择理科获得的额外喜悦值。

    OUTPUT

    输出一个整数,表示喜悦值总和的最大值

    SAMPLE

    INPUT

    1 2
    1 1
    100 110
    1
    1000

    OUTPUT

    1210

    解题报告

    选择不同时不能得到额外的权值,所以源点对所有点来说都是文科,汇点对所有点来说都是理科。
    对于单独两个点来说,只有两种情况。
    若两个人都选文科,需要割掉第2,4条边,代价为两个人选理科分别的贡献,以及他们一起选理科的贡献,因为所有的点都是等价的,2,4边的权值除各自选理科贡献外再加上一半的额外贡献。
    若两个人都选择理科同理。
    若两个人选择不同,假设x选择文科,y选择理科,那么需要割掉2,3,5。
    此时2,3权值和为分别选择科目的贡献和一半的同时选择理科和同时选择文科的贡献。还需再减去剩余的一半,即应是5的权值。(x,y间要建双向边。)
      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<queue>
      5 using namespace std;
      6 inline int read(){
      7     int sum(0);
      8     char ch(getchar());
      9     for(;ch<'0'||ch>'9';ch=getchar());
     10     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
     11     return sum;
     12 }
     13 struct edge{
     14     int e,n,w;
     15 }a[200001];
     16 int pre[10010],tot;
     17 inline void insert(int s,int e,int w){
     18     a[tot].e=e;
     19     a[tot].w=w;
     20     a[tot].n=pre[s];
     21     pre[s]=tot++;
     22 }
     23 int n,m;
     24 int w[101][101],l[101][101];
     25 int jz1[101][101],jz2[101][101],jz3[101][101],jz4[101][101];
     26 int sum(0),ans(0),inf(0x7fffffff);
     27 int S(0),T;
     28 int id[101][101];
     29 inline void init(){
     30     freopen("nt2011_happiness.in","r",stdin);
     31     freopen("nt2011_happiness.out","w",stdout);
     32     memset(pre,-1,sizeof(pre));
     33     n=read(),m=read();
     34     T=n*m+1;
     35     for(int i=1;i<=n;i++)
     36         for(int j=1;j<=m;j++)
     37             w[i][j]=read()<<1,sum+=w[i][j]>>1,id[i][j]=(i-1)*m+j;
     38     for(int i=1;i<=n;i++)
     39         for(int j=1;j<=m;j++)
     40             l[i][j]=read()<<1,sum+=l[i][j]>>1;
     41     for(int i=1;i<n;i++)
     42         for(int j=1;j<=m;j++)
     43             jz1[i][j]=read(),sum+=jz1[i][j];
     44     for(int i=1;i<n;i++)
     45         for(int j=1;j<=m;j++)
     46             jz2[i][j]=read(),sum+=jz2[i][j];
     47     for(int i=1;i<=n;i++)
     48         for(int j=1;j<m;j++)
     49             jz3[i][j]=read(),sum+=jz3[i][j];
     50     for(int i=1;i<=n;i++)
     51         for(int j=1;j<m;j++)
     52             jz4[i][j]=read(),sum+=jz4[i][j];
     53 }
     54 inline void build(){
     55     for(int i=1;i<=n;i++)
     56         for(int j=1;j<=m;j++){
     57             insert(S,id[i][j],w[i][j]+jz1[i][j]+jz1[i-1][j]+jz3[i][j]+jz3[i][j-1]),insert(id[i][j],S,0);
     58             insert(id[i][j],T,l[i][j]+jz2[i][j]+jz2[i-1][j]+jz4[i][j]+jz4[i][j-1]),insert(T,id[i][j],0);
     59         }
     60     for(int i=1;i<=n;i++)
     61         for(int j=1;j<=m;j++){
     62             if(i!=n)
     63                 insert(id[i][j],id[i][j]+m,jz1[i][j]+jz2[i][j]),insert(id[i][j]+m,id[i][j],jz1[i][j]+jz2[i][j]);
     64             if(j!=m)
     65                 insert(id[i][j],id[i][j]+1,jz3[i][j]+jz4[i][j]),insert(id[i][j]+1,id[i][j],jz3[i][j]+jz4[i][j]);
     66         }
     67 }
     68 int dis[10020];
     69 inline bool bfs(int s,int t){
     70     memset(dis,0,sizeof(dis));
     71     dis[s]=1;
     72     queue<int>q;
     73     q.push(s);
     74     while(!q.empty()){
     75         int k(q.front());
     76         q.pop();
     77         for(int i=pre[k];i!=-1;i=a[i].n){
     78             int e(a[i].e);
     79             if(!dis[e]&&a[i].w){
     80                 dis[e]=dis[k]+1;
     81                 q.push(e);
     82                 if(e==t)
     83                     return true;
     84             }
     85         }
     86     }
     87     return false;
     88 }
     89 inline int my_min(int a,int b){
     90     return a<b?a:b;
     91 }
     92 inline int dfs(int now,int flow){
     93     if(now==T)
     94         return flow;
     95     int tmp(flow),f;
     96     for(int i=pre[now];i!=-1;i=a[i].n){
     97         int e(a[i].e);
     98         if(dis[e]==dis[now]+1&&tmp&&a[i].w){
     99             f=dfs(e,my_min(tmp,a[i].w));
    100             if(!f){
    101                 dis[e]=0;
    102                 continue;
    103             }
    104             a[i].w-=f;
    105             a[i^1].w+=f;
    106             tmp-=f;
    107         }
    108     }
    109     return flow-tmp;
    110 }
    111 inline void dinic(){
    112     while(bfs(S,T))
    113         ans+=dfs(S,inf);
    114     printf("%d",sum-(ans>>1));
    115 }
    116 inline int gg(){
    117     init();
    118     build();
    119     dinic();
    120     return 0;
    121 }
    122 int K(gg());
    123 int main(){;}
    View Code
  • 相关阅读:
    LeetCode(65) Valid Number
    LeetCode(57) Insert Interval
    Python 之scrapy框架58同城招聘爬取案例
    Python 之12306网站验证码校验案例
    Python 之selenium+phantomJS斗鱼抓取案例
    Python 之pytesseract模块读取知乎验证码案例
    Python 之糗事百科多线程爬虫案例
    Python 之beautifulSoup4解析库
    Python 之lxml解析库
    把一张的数据添加到另一张中
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7277691.html
Copyright © 2011-2022 走看看