7.30noip测试

第一题:木桶研究

题意:给n块木板,选任意块组成一个水桶,其容量视为最短板的长度。现给出n块木板及其长度,求选单数块木板容量和与双数块木板容量和之差。

题解:对每块木板分析,其对答案贡献是与比其大者之组合数之差。化简可得所求实为最长板;sort一下即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
	int i=0,f=1;
	char ch;
	for(ch=getchar();!isdigit(ch);ch=getchar())
		if(ch=='-') f=-1;
	for(;isdigit(ch);ch=getchar())
		i=(i<<1)+(i<<3)+(ch^48);
	return i*f;
}
int buf[1024];
inline void write(int i){
	if(!i){putchar('0');return ;}
	if(i<0){putchar('-');i=-i;}
	while(i)buf[++buf[0]]=i%10,i/=10;
	while(buf[0]) putchar(buf[buf[0]--]+48);
	return ;
}
int n,w[1010];
signed main(){
	n=read();
	for(int i=1;i<=n;++i)
		w[i]=read();
	sort(w+1,w+n+1);
	write(w[n]);
	return 0;
}


第二题:木料开销

题意:给两个迭代函数求第n大值

题解:两个单调队列每次取最小值,注意去重

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
	int i=0,f=1;
	char ch;
	for(ch=getchar();!isdigit(ch);ch=getchar())
		if(ch=='-') f=-1;
	for(;isdigit(ch);ch=getchar())
		i=(i<<1)+(i<<3)+(ch^48);
	return i*f;
}
int buf[1024];
inline void write(long long i){
	if(!i){putchar('0');return ;}
	if(i<0){putchar('-');i=-i;}
	while(i)buf[++buf[0]]=i%10,i/=10;
	while(buf[0]) putchar(buf[buf[0]--]+48);
	return ;
}
int z,n;
long long u1,v1,w1,u2,v2,w2,que1[10001000],que2[10001000];
int l1,l2,r1,r2;
signed main(){
	z=read();n=read();
	u1=read();v1=read();w1=read();
	u2=read();v2=read();w2=read();
	if(n==1){
		write(z);
		return 0;
	}else{
		l1=r1=l2=r2=1;
		que1[l1]=u1*z/w1+v1;
		que2[l2]=u2*z/w2+v2;
		for(int i=2;i<n;++i){
			if(que1[l1]<que2[l2]){
				que1[++r1]=u1*que1[l1]/w1+v1;
				que2[++r2]=u2*que1[l1]/w2+v2;
				++l1;
			}else{
				que1[++r1]=u1*que2[l2]/w1+v1;
				que2[++r2]=u2*que2[l2]/w2+v2;
				++l2;
				if(que1[l1]==que2[l2-1]) ++l1;
			}
		}
		write(min(que1[l1],que2[l2]));
	}
	return 0;
}


第三题:木材运输

题意:在一有向图内有三火车,求火车到点权值相差在一定范围内的方案数

题解:注意数据范围(n<=50),且无环,每个点挨个bfs一遍用n^3数组存即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#define mod 1000000007
using namespace std;
inline int read(){
	int i=0,f=1;
	char ch;
	for(ch=getchar();!isdigit(ch);ch=getchar())
		if(ch=='-') f=-1;
	for(;isdigit(ch);ch=getchar())
		i=(i<<1)+(i<<3)+(ch^48);
	return i*f;
}
int buf[1024];
inline void write(long long i){
	if(!i){putchar('0');return ;}
	if(i<0){putchar('-');i=-i;}
	while(i)buf[++buf[0]]=i%10,i/=10;
	while(buf[0]) putchar(buf[buf[0]--]+48);
	return ;
}
int p[100],n,m,a,b,s1,s2,s3,k,f[51][51][51][3],first[100],nxt[3000],goal[3000];
struct trains{
	int p1,p2,p3;
	inline bool check(){
		return (abs(p[p1]-p[p2])<=k)&&(abs(p[p1]-p[p3])<=k)&&(abs(p[p2]-p[p3])<=k);
	}
};
int dfs(trains pos,int w){
	if((w==0)&&!(pos.check())) return 0;
	int x=pos.p1,y=pos.p2,z=pos.p3;
	if(f[x][y][z][w]!=-1) return f[x][y][z][w];
	if(w==0) f[x][y][z][w]=1; else f[x][y][z][w]=0;
	if(w==0) 
		for(int p=first[x];p;p=nxt[p])
			f[x][y][z][w]=(f[x][y][z][w]+dfs((trains) {goal[p],y,z},1))%mod;
	if(w==1) 
		for(int p=first[y];p;p=nxt[p])
			f[x][y][z][w]=(f[x][y][z][w]+dfs((trains) {x,goal[p],z},2))%mod;
	if(w==2) 
		for(int p=first[z];p;p=nxt[p])
			f[x][y][z][w]=(f[x][y][z][w]+dfs((trains) {x,y,goal[p]},0))%mod;
	return f[x][y][z][w];
}
signed main(){
	memset(f,-1,sizeof(f));
	n=read();m=read();k=read();
	for(int i=1;i<=n;++i)
		p[i]=read();
	for(int i=1;i<=m;++i){
		a=read();b=read();
		nxt[i]=first[a];
		first[a]=i;
		goal[i]=b;
	}
	s1=read();s2=read();s3=read();
	write(dfs((trains){s1,s2,s3},0));
	return 0;
}


第四题:木板排放

题意:n*m格图中放1*2之块,求方案数是否为1

题解:正解是两次二分图最大匹配,但是爆搜n+m遍也可以过...

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
	int i=0,f=1;
	char ch;
	for(ch=getchar();!isdigit(ch);ch=getchar())
		if(ch=='-') f=-1;
	for(;isdigit(ch);ch=getchar())
		i=(i<<1)+(i<<3)+(ch^48);
	return i*f;
}
int buf[1024];
inline void write(long long i){
	if(!i){putchar('0');return ;}
	if(i<0){putchar('-');i=-i;}
	while(i)buf[++buf[0]]=i%10,i/=10;
	while(buf[0]) putchar(buf[buf[0]--]+48);
	return ;
}
const int xmove[4]={0,1,-1,0};
const int ymove[4]={1,0,0,-1};
char c[100][100];
int n,m,cnt,ii,jj;
signed main(){
	n=read();m=read();
	for(int i=1;i<=n;++i)
		scanf("%s",c[i]+1);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			if(c[i][j]=='.') ++cnt;
	if(cnt&1)puts("No");
	else{
		for(int t=1;t<=(n+m);++t){
			for(int i=1;i<=n;++i)
				for(int j=1;j<=m;++j)
					if(c[i][j]=='.'){
						cnt=0;
						for(int k=0;k<4;++k){
							ii=i+xmove[k];
							jj=j+ymove[k];
							if(c[ii][jj]=='.') ++cnt;
						}
						if(cnt==1){
							c[i][j]='*';
							for(int k=0;k<4;++k){
								ii=i+xmove[k];
								jj=j+ymove[k];
								c[ii][jj]='*';
							}
						}
					}
		}
		for(int i=1;i<=n;++i)
			for(int j=1;j<=m;++j)
				if(c[i][j]=='.'){
					puts("No");
					return 0;
				}
		puts("Yes");
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值