• bzoj 1565 [NOI2009]植物大战僵尸 解题报告


    1565: [NOI2009]植物大战僵尸

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 2161  Solved: 1000
    [Submit][Status][Discuss]

    Description

    Input

    Output

    仅包含一个整数,表示可以获得的最大能源收入。注意,你也可以选择不进行任何攻击,这样能源收入为0。

    Sample Input

    3 2
    10 0
    20 0
    -10 0
    -5 1 0 0
    100 1 2 1
    100 0

    Sample Output

    25

    HINT

    在样例中, 植物P1,1可以攻击位置(0,0), P2, 0可以攻击位置(2,1)。 
    一个方案为,首先进攻P1,1, P0,1,此时可以攻击P0,0 。共得到能源收益为(-5)+20+10 = 25。注意, 位置(2,1)被植物P2,0保护,所以无法攻击第2行中的任何植物。 
    【大致数据规模】
    约20%的数据满足1 ≤ N, M ≤ 5;
    约40%的数据满足1 ≤ N, M ≤ 10;
    约100%的数据满足1 ≤ N ≤ 20,1 ≤ M ≤ 30,-10000 ≤ Score ≤ 10000 。

    Source

     
    [Submit][Status][Discuss]


    HOME Back

    ————————————————我是分割线——————————————————————————

    好题啊好题

    这题折腾了三天,差点没吐出血来。

    先拓扑排序求环,把环删掉。

    之后重建图求最大权闭合子图,把一个植物向保护它的植物连边,跑一遍网络流即可。

    第一次只过了4个点。不明所以。

    换方法重写了拓扑,在网络流中加限制乱搞。

    终于90,但第九个点一直RE,最后发现数组开小了。这题最多600个点,但边数组一直开到800005才A了。TAT~

      1 /*
      2     Problem: bzoj 1565 [NOI2009]植物大战僵尸
      3     OJ:         bzoj
      4     User:    S.B.S.
      5     Time:     264 MS
      6     Memory:     13884 KB
      7     Length:  6934 B
      8 */
      9 #include<iostream>
     10 #include<cstdio>
     11 #include<cstring>
     12 #include<cmath>
     13 #include<algorithm>
     14 #include<queue>
     15 #include<cstdlib>
     16 #include<iomanip>
     17 #include<cassert>
     18 #include<climits>
     19 #include<functional>
     20 #include<bitset>
     21 #include<vector>
     22 #include<list>
     23 #define F(i,j,k) for(int i=j;i<=k;++i)
     24 #define M(a,b) memset(a,b,sizeof(a))
     25 #define FF(i,j,k) for(int i=j;i>=k;i--)
     26 #define inf 0x3f3f3f3f
     27 #define maxm 1001
     28 #define mod 998244353
     29 //#define LOCAL
     30 using namespace std;
     31 int read(){
     32     int x=0,f=1;char ch=getchar();
     33     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     34     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     35     return x*f;
     36 }
     37 int n,m;
     38 int mp[2000];
     39 struct EDGE
     40 {
     41     int from;
     42     int to;
     43     int value;
     44     int next;
     45 }e[800005];
     46 int head[4001];
     47 int v[4001],in[4001],out[4001];
     48 int tot=1;
     49 inline void addedge(int u,int v,int w)
     50 {
     51     e[++tot].from=u;
     52     e[tot].to=v;
     53     e[tot].value=w;
     54     e[tot].next=head[u];
     55     head[u]=tot;
     56 //    tot++;
     57 }
     58 //bool kan[2000][2000];
     59 int ans=0;
     60 //inline int at(int x,int y)
     61 //{
     62 //    return m*x+y+1;
     63 //}
     64 //int stk[4001],top=0;
     65 //inline void topsort()
     66 //{
     67 //    int temp[4001];M(temp,0);
     68 //    F(i,1,m*n) temp[i]=in[i];
     69 //    F(i,1,m*n){
     70 //        if(in[i]==0){
     71 //            stk[top]=i;
     72 ////            cout<<i<<"********"<<endl;
     73 //            top++;
     74 //        }
     75 //    }
     76 ////    cout<<top<<": "<<endl;
     77 ////    F(i,0,top-1) cout<<stk[i]<<" ";cout<<endl;
     78 //    while(top!=0){
     79 //        top--;int u=stk[top];
     80 //        for(int i=head[u];i!=-1;i=e[i].next)
     81 //        {
     82 //            in[e[i].to]--;
     83 //            if(in[e[i].to]==0){
     84 //                stk[top]=e[i].to;
     85 //                top++;
     86 //            }
     87 //        }
     88 //    }
     89 //    F(i,1,m*n){
     90 //        if(in[i]!=0){
     91 //            stk[top]=i;
     92 //            top++;
     93 //        }
     94 //    }
     95 //    while(top!=0){
     96 //        top--;int u=stk[top];
     97 //        temp[u]=-1;out[u]=-1;
     98 //        v[u]=0;
     99 //    }
    100 //    F(i,1,m*n) in[i]=temp[i];
    101 //    return;
    102 //}
    103 inline void add(int u,int v,int w)
    104 {
    105     addedge(u,v,w);
    106     addedge(v,u,0);
    107     ++in[u];
    108     return;
    109 }
    110 int map[4001];
    111 int S,T;
    112 bool ok()
    113 {  
    114     F(i,S,T) if(map[i]!=-2) map[i]=-1;
    115     int que[4001];  
    116     int hd=0,tl=0;  
    117     que[tl++]=S;  
    118     map[S]=1;  
    119     while (hd<tl){  
    120         int u=que[hd++];  
    121         for(int i=head[u];i;i=e[i].next)
    122         {  
    123             if(map[e[i].to]==-1&&e[i].value)
    124             {  
    125                 map[e[i].to]=map[u]+1;  
    126                 que[tl++]=e[i].to;  
    127             }  
    128         }  
    129     }  
    130 //    if (map[T]!=-1) return true;  
    131 //    else return false;  
    132     return map[T]>0;
    133 }  
    134 int cur[4000];
    135 int zeng(int k,int now)
    136 {  
    137     if (k==T) return now;  
    138     int r=0;  
    139     for (int i=cur[k];i&&now>r;i=e[i].next)
    140     {  
    141         if (map[k]+1==map[e[i].to]&&e[i].value)
    142         {  
    143             int t=zeng(e[i].to,min(now-r,e[i].value));  
    144             e[i].value-=t;e[i^1].value+=t;r+=t;  
    145             if(e[i].value) cur[k]=i;//***
    146 //            cout<<e[i].from<<" ---> "<<e[i].to<<" $ "<<t<<endl;
    147         }  
    148     }  
    149     if (!r) map[k]=-1;  
    150     return r;  
    151 }  
    152 int dinic()  
    153 {  
    154     int r=0,t;  
    155     M(cur,0);
    156     while (ok()){
    157         for(int i=S;i<=T;++i) cur[i]=head[i];
    158         r+=zeng(S,inf);
    159 //        while(t=zeng(S,inf)) r+=t;  
    160     }
    161     return r;   
    162 }
    163 //pair<int,int> kk[4001];
    164 //int cur;
    165 int main()
    166 {
    167     std::ios::sync_with_stdio(false);//cout<<setiosflags(ios::fixed)<<setprecision(1)<<y;
    168     #ifdef LOCAL
    169     freopen("111.in","r",stdin);
    170     freopen("data.out","w",stdout);
    171     #endif
    172     cin>>n>>m;
    173     S=0;T=m*n+1;
    174     M(mp,0);M(head,0);
    175 //    F(i,0,n-1)F(j,0,m-1){
    176 //        int x,y;
    177 //        cin>>x>>y;
    178 //        mp[i][j]=x;
    179 //        v[at(i,j)]=x;
    180 //        in[at(i,j)]++;
    181 //        if(j==m-1) in[at(i,j)]--;
    182 //        if(j!=0) add(at(i,j),at(i,j-1),v[at(i-1,j)]);
    183 //        if(y==0) continue;
    184 ////        **********************************************
    185 //        F(k,1,y){
    186 //            int a,b;
    187 //            cin>>a>>b;
    188 //            kk[cur].first=at(i,j);
    189 //            kk[cur].second=at(a,b);
    190 //            cur++;
    191 //            in[at(a,b)]++;
    192 //            addedge(at(i,j),at(a,b),0);
    193 ////            cout<<at(i,j)<<" "<<at(a,b)<<" &&&&&"<<endl;
    194 //        }
    195 //    }
    196 //    F(i,1,m*n) cout<<in[i]<<" ";cout<<endl;    
    197 //    cout<<"/*****************************"<<endl;
    198 //    F(i,1,tot) cout<<e[i].from<<" ---> "<<e[i].to<<" $ "<<e[i].value<<endl;
    199 //    cout<<"*****************************/"<<endl;
    200     F(i,1,n*m){
    201         int temp;
    202         cin>>mp[i];
    203         if(mp[i]>0) add(S,i,mp[i]);
    204         else add(i,T,-mp[i]);
    205         cin>>temp;
    206         while(temp--){
    207             int x,y;
    208             cin>>x>>y;
    209             add(x*m+y+1,i,inf);
    210         }
    211         if(i%m) add(i,i+1,inf);
    212     }
    213 //    topsort();
    214 //    cout<<"))))))"<<endl;
    215 //    F(i,1,m*n) if(in[i]==-1) cout<<i<<" ";cout<<"((((("<<endl;
    216 //    M(e,0);M(head,-1);tot=0;
    217     int q[4000];M(q,0);
    218     int cur1=0,cur2=0;
    219     for(int i=S;i<=T;++i){
    220         if(!in[i]) q[cur2++]=i;
    221         map[i]=-2;
    222     } 
    223     int sum=0; 
    224     while(cur1<cur2){
    225         int cnt=q[cur1++];map[cnt]=0;
    226         if(mp[cnt]>0) sum+=mp[cnt];
    227         for(int i=head[cnt];i;i=e[i].next)
    228         {
    229             if(i&1) if(!--in[e[i].to]) q[cur2++]=e[i].to;
    230         }
    231     }
    232 //    F(i,1,m*n) cout<<in[i]<<" ";cout<<endl;    
    233 //    cout<<"v: "<<endl;
    234 //    F(i,1,m*n) cout<<v[i]<<" ";cout<<endl;
    235 //    F(i,0,n-1)F(j,0,m-1){
    236 //        if(in[at(i,j)]==-1) continue;
    237 ////        cout<<at(i,j)<<" : "<<in[at(i,j)]<<"@ "<<endl;
    238 //        if(j!=0&&in[at(i,j-1)]!=-1) add(at(i,j-1),at(i,j),inf);
    239 //        if(v[at(i,j)]==0) continue;
    240 //        if(v[at(i,j)]>0) add(31,at(i,j),v[at(i,j)]),sum+=v[at(i,j)];
    241 //        else add(at(i,j),32,-v[at(i,j)]);
    242 //    }
    243 //    while(cur!=0){
    244 //        cur--;
    245 //        if(in[kk[cur].first]==-1||in[kk[cur].second]==-1) continue;
    246 //        int u=kk[cur].first;
    247 //        int v=kk[cur].second;
    248 //        add(v,u,inf);
    249 //    }
    250 //    cout<<"/*****************************"<<endl;
    251 //    F(i,1,tot) cout<<e[i].from<<" ---> "<<e[i].to<<" $ "<<e[i].value<<endl;
    252 //    cout<<"*****************************/"<<endl;
    253 //    cout<<sum<<endl;
    254     cout<<sum-dinic()<<endl;
    255     return 0;
    256 }
    257 /*
    258 3 2
    259 10 0
    260 20 0
    261 -10 0
    262 -5 1 0 0
    263 100 1 2 1
    264 100 0
    265 */
    植物大战僵尸
  • 相关阅读:
    三列布局_左右绝对定位_中间适应
    三列布局_左右固定_中间自适应
    两列布局_左右二侧_绝对定位
    二列布局_左右固定_自己撑开父级块
    两列布局_右侧固定_左侧自适应
    两列布局_左侧固定_右侧自适应
    单列布局_宽度自适应_内容居中
    单列布局_上中下等宽
    聊一聊Unity协程背后的实现原理
    发火箭和做游戏有什么共通点?
  • 原文地址:https://www.cnblogs.com/SBSOI/p/5889511.html
Copyright © 2020-2023  润新知