Loading

测试「20201104测试总结」

搜索大赛。


T1

\(\mathrm{dp}(a,b,x,y)\) 表示用了 \(a\) 个白棋,\(b\) 个黑棋,所得到的序列的所有后缀中白棋最多比黑棋多 \(x\) 个,黑棋最多比白棋多 \(y\) 个的方案数。

若放白棋,有:

\[\mathrm{dp}(a,b,x,y)=\mathrm{dp}(a+1,b,x+1,\max(0,y-1)),x<k,a<n \]

若放黑棋,有:

\[\mathrm{dp}(a,b,x,y)=\mathrm{dp}(a,b+1,\max(0,x-1),y+1),y<k,b<m \]

考试的时候有点昏,想到的是把后缀中两种棋子最大的差放进状态中,结果没有想出转移方程,还是打了暴力。

\(\text{Code}:\)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=155;
const lxl mod=1e9+7;

template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

int n,m,k;
int f[maxn][maxn][25][25];

int dp(int a,int b,int x,int y)
{
	if(a==n&&b==m) return 1;
	if(~f[a][b][x][y]) return f[a][b][x][y];
	int res=0;
	if(a<n&&x<k) (res+=dp(a+1,b,x+1,max(0,y-1)))%=mod;
	if(b<m&&y<k) (res+=dp(a,b+1,max(0,x-1),y+1))%=mod;
	return f[a][b][x][y]=res;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("chess.in","r",stdin);
	freopen("chess.out","w",stdout);
#endif
	read(n),read(m),read(k);
	memset(f,-1,sizeof(f));
	printf("%d\n",dp(0,0,0,0));
	return 0;
}

T2

记忆化搜索。

毫无头绪,打了暴力。

\(\text{Code}:\)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=2001;

template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

int n,k;
int st[maxn],ed[maxn];
int ans=INF;
int f[11][maxn][11][11][11];

int dp(int pos,int now,int a,int b,int c)
{
	if(~f[pos][now][a][b][c]) return f[pos][now][a][b][c];
	int res=INF;
	// 下一个人
	if(a) res=min(res,dp(a,now,0,b,c)+abs(a-pos)+1);
	if(b) res=min(res,dp(b,now,a,0,c)+abs(b-pos)+1);
	if(c) res=min(res,dp(c,now,a,b,0)+abs(c-pos)+1);
	if(now>n)
	{
		if(!a&&!b&&!c) return 0;
		return f[pos][now][a][b][c]=res;
	}
	if(a&&b&&c) // 先接下一个人,再下一个人
	{
		res=min(res,dp(ed[now],now+1,a,b,c)+abs(pos-st[now])+abs(st[now]-ed[now])+2);
		res=min(res,dp(a,now+1,ed[now],b,c)+abs(pos-st[now])+abs(a-st[now])+2);
		res=min(res,dp(b,now+1,a,ed[now],c)+abs(pos-st[now])+abs(b-st[now])+2);
		res=min(res,dp(c,now+1,a,b,ed[now])+abs(pos-st[now])+abs(c-st[now])+2);
	}
	else if(!a) // 直接接下一个人
		res=min(res,dp(st[now],now+1,ed[now],b,c)+abs(pos-st[now])+1);
	else if(!b)
		res=min(res,dp(st[now],now+1,a,ed[now],c)+abs(pos-st[now])+1);
	else
		res=min(res,dp(st[now],now+1,a,b,ed[now])+abs(pos-st[now])+1);
	return f[pos][now][a][b][c]=res;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("taxi.in","r",stdin);
	freopen("taxi.out","w",stdout);
#endif
	read(n),read(k);
	for(int i=1;i<=n;++i)
		read(st[i]),read(ed[i]);
	memset(f,-1,sizeof(f));
	printf("%d\n",dp(1,1,0,0,0));
	return 0;
}

T3

折半搜索。

分别搜出前后两部分能组成哪些数,再二分查找最大能组成哪个数。

\(\text{Code}:\)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <set>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=1e6+5;

template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

int n,m,a[45];
set<int> s[2];
int ans;

void dfs(int x,int l,int r)
{
	if(l>r) return s[r==n].insert(x),ans=max(ans,x),void();
	dfs((x+a[l])%m,l+1,r);
	dfs(x,l+1,r);
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("stone.in","r",stdin);
	freopen("stone.out","w",stdout);
#endif
	read(n),read(m);
	for(int i=1;i<=n;++i) read(a[i]),a[i]%=m;
	dfs(0,1,n/2);
	dfs(0,n/2+1,n);
	for(set<int>::iterator it=s[0].begin();it!=s[0].end();++it)
	{
		ans=max(ans,(*it+*(--s[1].upper_bound(m-*it)))%m);
		ans=max(ans,(*it+*(--s[1].upper_bound(2*m-*it)))%m);
	}
	printf("%d\n",ans);
	return 0;
}

T4

神仙网络流。

将每个导弹能打到的点串起来,然后最小割。

\(\text{Code}:\)

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=55,maxm=2e5+5;

#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

struct edge
{
	int u,v,cp,next;
	edge(int u,int v,int cp,int next)
		:u(u),v(v),cp(cp),next(next){}
	edge(){}
}e[maxm<<1];

int head[maxn*maxn<<1],ecnt;

inline void add(int u,int v,int cp)
{
	e[ecnt]=edge(u,v,cp,head[u]);
	head[u]=ecnt++;
	e[ecnt]=edge(v,u,0,head[v]);
	head[v]=ecnt++;
}

int n,m;
int wy[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int G[maxn][maxn];

int s,t;
int d[maxn*maxn<<1],gap[maxn*maxn<<1],nxt[maxn*maxn<<1];

inline void bfs()
{
	queue<int> q;
	memset(d,0,sizeof(d));
	memset(gap,0,sizeof(gap));
	++gap[d[t]=1];
	q.push(t);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		nxt[u]=head[u];
		for(int i=head[u];~i;i=e[i].next)
		{
			int v=e[i].v;
			if(d[v]) continue;
			++gap[d[v]=d[u]+1];
			q.push(v);
		}
	}
}

int ISAP(int u,int flow)
{
	if(u==t||!flow) return flow;
	int rest=flow;
	for(int &i=nxt[u];~i;i=e[i].next)
	{
		int v=e[i].v;
		if(!e[i].cp||d[v]+1!=d[u]) continue;
		int k=ISAP(v,min(e[i].cp,rest));
		if(!k) continue;
		e[i].cp-=k;
		e[i^1].cp+=k;
		rest-=k;
		if(!rest) return flow;
	}
	nxt[u]=head[u];
	if(!--gap[d[u]]) d[s]=t+1;
	++gap[++d[u]];
	return flow-rest;
}

inline int pos(int x,int y) {return (x-1)*m+y;}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("missile.in","r",stdin);
	freopen("missile.out","w",stdout);
#endif
	read(n),read(m);
	memset(head,-1,sizeof(head));
	s=1;t=n*m*2+2;
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
		{
			read(G[i][j]);
			add(pos(i,j)<<1,pos(i,j)<<1|1,INF);
		}
	int maxflow=0;
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
		{
			if(G[i][j]>=0) continue;
			int type=abs(G[i][j])-1;
			if(type<=1) add(s,pos(i,j)<<1,INF);
			else add(pos(i,j)<<1|1,t,INF);
			int px=i,py=j,x=px+wy[type][0],y=py+wy[type][1];
			if(x>n||x<1||y>m||y<1) continue;
			int Max=0;
			while(x<=n&&y<=m&&x>=1&&y>=1)
			{
				Max=max(Max,max(0,G[x][y]));
				x+=wy[type][0];y+=wy[type][1];
			}
			x=px+wy[type][0],y=py+wy[type][1];
			while(x<=n&&y<=m&&x>=1&&y>=1)
			{
				if(type<=1) add(pos(px,py)<<1,pos(x,y)<<1,Max-max(0,G[px][py]));
				else add(pos(x,y)<<1|1,pos(px,py)<<1|1,Max-max(0,G[px][py]));
				px+=wy[type][0];py+=wy[type][1];
				x+=wy[type][0];y+=wy[type][1];
			}
			maxflow+=Max;
		}
	bfs();
	while(d[s]<=t)
		maxflow-=ISAP(s,1<<30);
	printf("%d\n",maxflow);
	return 0;
}
posted @ 2020-11-04 20:37  GoPoux  阅读(98)  评论(0编辑  收藏  举报