【过题记录】8.4(robocom补题,网络流)

今天robocom国赛,因为一个bool函数忘记return 1而裂开(错失21分)
以此为戒


贪心消消乐

在这里插入图片描述


其实就是一个求最大子矩阵和的板子题
利用最大子段和的思想
枚举矩阵中的上下界
压成一维后利用最大子段和 O ( n ) O(n) O(n)处理
复杂度 O ( n 3 ∗ k ) O(n^3*k) O(n3k)
k为执行次数


#include<bits/stdc++.h>
using namespace std;

#define int long long

const int N = 5010;
int a[N][N];
int n;
int sum[N][N];
int maxn = 0;
int s[N][N],ss[N][N];
int tot = 0;
int stx,sty,edx,edy,xx,XX,yy,YY;
int cnt = 0;

void Swap(){
	xx = sty; XX = edy; yy = stx; YY = edx;
} 
int ce =0 ;
bool Work(){
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= n; j++){
	  	  s[j][i] = s[j][i-1]+a[i][j];
		  ss[j][i] = ss[j][i-1];
		  if (a[i][j] == 0) ss[j][i]++; 
	  }
	int maxx = 0;
	xx = n+1; yy = n+1; XX = n+1; YY = n+1;
	for (stx = 1; stx <= n; stx++){
		for (edx = stx; edx <= n; edx++){
			int sum = 0;
			sty = 1;
			for (edy = 1; edy <= n; edy++){
				if (sum > maxx) Swap();
				int now = s[edy][edx]-s[edy][stx-1];
				int nowz = ss[edy][edx]-ss[edy][stx-1];
				if (nowz!=0){
					sty = edy+1;
					sum = 0;
					continue;
				}
			    if (sum < 0){
				    sum = 0;
				    sty = edy;
				}
				sum+=now;
				if (sum > maxx) maxx = sum,Swap();
				if (sum == maxx){
					if (sty < xx) Swap();
					else if (sty == xx&&stx < yy) Swap();
					else if (sty == xx && stx == yy&&edy < XX) Swap();
					else if (sty == xx && stx == yy&&edy == XX && edx < YY) Swap();
				}
			}
		}
	}
	if (maxx == 0) return 0;
	tot+=maxx;
	printf("(%lld, %lld) (%lld, %lld) %lld\n",xx,yy,XX,YY,maxx);
    swap(xx,yy); swap(XX,YY);
	int delx = XX-xx+1;
	for (int i = xx-1; i >= 1; i--)
	  for (int j = yy; j <= YY; j++)
	    a[i+delx][j] = a[i][j];
	for (int i = 1; i <= delx; i++)
	  for (int j = yy; j <= YY; j++) a[i][j] = 0;
	cnt++;
	bool f = 0;
	return 1;
}

signed main(){
	cin>>n;
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= n; j++){
	      cin>>a[i][j];
	      if (a[i][j] > 0) maxn+=a[i][j],ce++;
	  }
	while (Work()); cout<<tot<<endl;
}

拍照

一道最大权值闭合图的板子题
按如下方式连边:
在这里插入图片描述

最大全职就是 s u m − m a x f l o w sum-maxflow summaxflow
证明尚未完全理清
等我理清了来补


#include<bits/stdc++.h>
using namespace std;

const int N = 7e3+100,inf = 1e9+7;
struct Node{
	int y,Next,v;
}e[2*N];
int len,Linkk[N];
int st,ed;

void Insert(int x,int y,int v){
	e[++len] = (Node){y,Linkk[x],v};
	Linkk[x] = len;
}

queue < int > q;
int d[N];

bool bfs(){
	for (int i = 1; i <= ed; i++) d[i] = 0;
	while (q.size()) q.pop();
	d[st] = 1; q.push(st);
	while (q.size()){
		int x = q.front(); q.pop();
		for (int i = Linkk[x]; i; i = e[i].Next){
			int y = e[i].y; if (!e[i].v ||d[y]) continue;
			d[y] = d[x]+1; q.push(y);
			if (y == ed) return 1;
		}
	}
	return 0;
}

int dinic(int x,int flow){
	if (x == ed) return flow;
	int re = flow , k;
	for (int i = Linkk[x]; i; i = e[i].Next){
		int y = e[i].y; if (!e[i].v || d[y] != d[x]+1) continue;
		k = dinic(y,min(re,e[i].v));
		if (!k) d[y] = 0;
		re-=k;
		e[i].v-=k; e[i^1].v+=k;
	}
	return flow-re;
}

int n,m;
int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	cin>>m>>n; len = 1;
	st = n+m+1; ed = n+m+2;
	int sum = 0;
	for (int i = 1; i <= m; i++){
		int v; cin>>v; sum+=v;
		Insert(st,i,v); Insert(i,st,0);
		int x;
		cin>>x;
		while (x){
			Insert(i,x+m,inf); Insert(x+m,i,0);
			cin>>x;
		}
	}
	for (int i = m+1,x; i <= m+n; i++)
	  cin>>x,Insert(i,ed,x),Insert(ed,i,0);
	int flow;
	int maxf = 0;
	while (bfs())
	  while (flow = dinic(st,inf)) maxf+=flow;
	cout<<sum-maxf<<endl;
	return 0;
}

太空飞行计划问题


与上体一样
所多的就是输出方案
这里最大流用的是dinic算法
如果最后对于一个点i,d[i]不为0,说明这个点在分层图中出现,并且用上了
那么就说明这个仪器用上了


#include<bits/stdc++.h>
using namespace std;

const int N = 7e3+100,inf = 1e9+7;
struct Node{
	int y,Next,v;
}e[2*N];
int len,Linkk[N];
int st,ed;

void Insert(int x,int y,int v){
	e[++len] = (Node){y,Linkk[x],v};
	Linkk[x] = len;
}

queue < int > q;
int d[N];

bool bfs(){
	for (int i = 1; i <= ed; i++) d[i] = 0;
	while (q.size()) q.pop();
	d[st] = 1; q.push(st);
	while (q.size()){
		int x = q.front(); q.pop();
		for (int i = Linkk[x]; i; i = e[i].Next){
			int y = e[i].y; if (!e[i].v ||d[y]) continue;
			d[y] = d[x]+1; q.push(y);
			if (y == ed) return 1;
		}
	}
	return 0;
}

int dinic(int x,int flow){
	if (x == ed) return flow;
	int re = flow , k;
	for (int i = Linkk[x]; i; i = e[i].Next){
		int y = e[i].y; if (!e[i].v || d[y] != d[x]+1) continue;
		k = dinic(y,min(re,e[i].v));
		if (!k) d[y] = 0;
		re-=k;
		e[i].v-=k; e[i^1].v+=k;
	}
	return flow-re;
}

int flag;
int re(){
    char c;int r=0;
    while (c<'0' || c>'9') c=getchar();
    while (c>='0' && c<='9')
    {
        r=r*10+c-'0';
        c=getchar();
    }
    if (c=='\r') flag=1;
    return r;
}

int n,m;
int main(){
//	cin.tie(0);
//	ios::sync_with_stdio(false);
	scanf("%d %d",&m,&n); len = 1;
	st = n+m+1; ed = n+m+2;
	int sum = 0;
	for (int i = 1; i <= m; i++){
		int v; scanf("%d",&v); sum+=v;
		Insert(st,i,v); Insert(i,st,0);
		int x; flag = 0;
		while (getchar() == ' '){
			scanf("%d",&x);
			Insert(i,x+m,inf); Insert(x+m,i,0); 
//			cout<<"x = "<<x<<endl; 
		}
	}
//	cout<<"OK";
	for (int i = m+1,x; i <= m+n; i++)
	  scanf("%d",&x),Insert(i,ed,x),Insert(ed,i,0);
	int flow;
	int maxf = 0;
	while (bfs())
	  while (flow = dinic(st,inf)) maxf+=flow;
	for (int i = 1; i <= m; i++) if (d[i]) cout<<i<<' ';
	cout<<endl;
	for (int i = 1; i <= n; i++) if (d[i+m]) cout<<i<<' '; cout<<endl;
	cout<<sum-maxf<<endl;
	return 0;
}
  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值