JZOJ 5602. 【NOI2018模拟3.26】Cti JZOJ 5057. 【GDSOI2017模拟4.13】炮塔
Description
有一個 n × m 的地圖, 地圖上的每一個位置可以是空地, 炮塔或是敵人. 你需要操縱炮塔消滅敵人.
對于每個炮塔都有一個它可以瞄準的方向, 你需要在它的瞄準方向上確定一個它的攻擊位置,當然也可以不進行攻擊. 一旦一個位置被攻擊, 則在這個位置上的所有敵人都會被消滅.
保證對于任意一個炮塔, 它所有可能的攻擊位置上不存在另外一個炮塔.
定義炮彈的運行軌跡為炮彈的起點和終點覆蓋的區(qū)域. 你需要求出一種方案, 使得沒有兩條炮彈軌跡相交.
Input
第一行兩個整數(shù) n,m.
接下來 n 行, 每行 m 個整數(shù), 0 表示空地, ?1,?2,?3,?4 分別表示瞄準上下左右的炮塔, 正整
數(shù) p 表示表示此位置有 p 個敵人.
Output
一行一個整數(shù)表示答案.
Sample Input
輸入1:
3 2
0 9
-4 3
0 -1
輸入2:
4 5
0 0 -2 0 0
-4 0 5 4 0
0 -4 3 0 6
9 0 0 -1 0
Sample Output
輸出1:
9
輸出2:
12
Data Constraint
對于前 20% 的數(shù)據(jù), n,m ≤ 5;
對于另 20% 的數(shù)據(jù), 朝向上下的炮塔至多有 2 個;
對于另 20% 的數(shù)據(jù), 至多有 6 個炮塔;
對于 100% 的數(shù)據(jù), 1 ≤ n,m ≤ 50, 每個位置的敵人數(shù)量 < 1000.
Solution
- 博主偷懶 COPY 一波題解:(感謝 YaLi_HYJ 大佬的詳細解析)
這題用網(wǎng)絡流解決問題十分巧妙,在解決相交的問題上采取了拆點的方法。
最后跑一遍最小割來求得最小代價即可。
Code
#include<cstdio> #include<cstring> #include<algorithm> #include<cctype> using namespace std; const int N=52,M=N*N<<1,inf=1e9; struct data {int x,y; }b[N*N]; int n,m,num,tot=1,p,ans,sum,s,t; int first[M],next[M<<1],en[M<<1],w[M<<1]; int a[N][N],d[N][N],r[M],c[M]; int dis[M],gap[M],cur[M]; inline int read() {int X=0,w=0; char ch=0;while(!isdigit(ch)) w|=ch=='-',ch=getchar();while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } inline int min(int x,int y) {return x<y?x:y; } inline void ins(int x,int y,int z) {next[++tot]=first[x];first[x]=tot;en[tot]=y;w[tot]=z; } inline void insert(int x,int y,int z) {ins(x,y,z),ins(y,x,0); } int sap(int x,int y) {if(x==t) return y;int use=0;for(int i=cur[x];i;i=next[i])if(w[i] && dis[x]==dis[en[i]]+1){cur[x]=i;int z=sap(en[i],min(w[i],y-use));w[i]-=z,w[i^1]+=z,use+=z;if(dis[s]>p || use==y) return use;}cur[x]=first[x];if(!--gap[dis[x]]) dis[s]=p+1;gap[++dis[x]]++;return use; } int main() {n=read(),m=read();s=++p,t=++p;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){a[i][j]=read();if(a[i][j]<0) b[++num]=(data){i,j};int x=d[i][j]=(i-1)*m+j;r[x]=++p,c[x]=++p;insert(c[x],r[x],inf);}for(int i=1;i<=num;i++){int xx=b[i].x,yy=b[i].y,k=a[xx][yy];int x=d[xx][yy];if(k==-1 || k==-2) insert(s,c[x],inf); else insert(r[x],t,inf);if(k==-1){int mx=0,pos=0;for(int j=xx;j;j--)if(a[j][yy]>mx) mx=a[pos=j][yy];if(!mx) continue;sum+=mx;for(int j=xx;j>=pos;j--)if(j>1) insert(c[d[j][yy]],c[d[j-1][yy]],mx-(a[j][yy]<0?0:a[j][yy]));}elseif(k==-2){int mx=0,pos=0;for(int j=xx;j<=n;j++)if(a[j][yy]>mx) mx=a[pos=j][yy];if(!mx) continue;sum+=mx;for(int j=xx;j<=pos;j++)if(j<n) insert(c[d[j][yy]],c[d[j+1][yy]],mx-(a[j][yy]<0?0:a[j][yy]));}elseif(k==-3){int mx=0,pos=0;for(int j=yy;j;j--)if(a[xx][j]>mx) mx=a[xx][pos=j];if(!mx) continue;sum+=mx;for(int j=yy;j>=pos;j--)if(j>1) insert(r[d[xx][j-1]],r[d[xx][j]],mx-(a[xx][j]<0?0:a[xx][j]));}else{int mx=0,pos=0;for(int j=yy;j<=m;j++)if(a[xx][j]>mx) mx=a[xx][pos=j];if(!mx) continue;sum+=mx;for(int j=yy;j<=pos;j++)if(j<m) insert(r[d[xx][j+1]],r[d[xx][j]],mx-(a[xx][j]<0?0:a[xx][j]));}}for(int i=1;i<=p;i++) cur[i]=first[i];gap[0]=p;while(dis[s]<=p) ans+=sap(s,inf);printf("%d",sum-ans);return 0; } 與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的JZOJ 5602. 【NOI2018模拟3.26】Cti JZOJ 5057. 【GDSOI2017模拟4.13】炮塔的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JZOJ 5603. 【NOI2018模
- 下一篇: JZOJ 5606. 【NOI2018模