2018.02.01【NOIP普及组】模拟赛D组

JZOJ NO.1 【2012.02.25普及组】牛车

题目

这道题就是同车道前面有x头牛,车速降低D*X,低于最低限速不允许,一共可以有多少辆车


代码

#include <cstdio>
using namespace std;
int a[1000001],n,ans,x,maxn,u,m,d,l,e;
int max(int a,int b){return (a>b)?a:b;}
int main(){
	scanf("%d%d%d%d",&n,&m,&d,&l);
	for (int i=1;i<=n;i++){
	scanf("%d",&x);
	if (x>=l){
		a[(x-l)/d+1]++; //最少要插到第几行
		maxn=max(maxn,(x-l)/d+1);//桶排
	}
	} e=m;
	for (int i=1;i<=maxn;i++){
		if (a[i]==0){e+=m;continue;}//可以增加内存
		if (a[i]<=e) {ans+=a[i];e-=a[i];}//可以插入
		else {ans+=e;e=0;} //最多插完内存
		e+=m;//为下一行增加内存
	}
	printf("%d",ans);
	return 0;
}

JZOJ NO.2 【2012.02.25普及组】危险系数

分析

就是求它的最短路径,不多解释。


代码

#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,a[10001],f[101][101],ans;
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++) scanf("%d",&a[i]);
	for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf("%d",&f[i][j]);
	for (int k=1;k<=n;k++)
	for (int i=1;i<=n;i++)
	for (int j=1;j<=n;j++) 
	if (i!=j&&i!=k&&j!=k) f[i][j]=min(f[i][j],f[i][k]+f[k][j]);//floyd
	for (int i=1;i<=m-1;i++) ans+=f[a[i]][a[i+1]];
	printf("%d",ans); return 0;
}

JZOJ NO.3 【普及模拟】前缀转后缀

分析

模拟建树,再用后序遍历输出。


代码

#include <cstdio>
#include <cctype>
using namespace std;
struct z{int lson,rson;}tree[201];
int n,m; char c[201],w;
int build(int x){
	m++;
	if (isdigit(c[x])){tree[x].lson=-1;tree[x].rson=-1;return x;}//是数字
	else {tree[x].lson=build(m+1); tree[x].rson=build(m+1);return x;}//是符号
}
void print(int x){
	if (tree[x].lson!=-1) print(tree[x].lson);//有左孩子
	if (tree[x].rson!=-1) print(tree[x].rson);//有右孩子
	printf("%c ",c[x]);
}
int main(){
	freopen("j4.in","r",stdin);
	freopen("j4.out","w",stdout);
	while ((c[++n]=getchar())!='\n'){
		w=getchar();
		if (w=='\n') break;} n--;
	build(1);//建树
	print(1);//输出
	return 0;
}

JZOJ NO.4 【普及模拟】游戏

首先先放记忆化搜索的代码。

#include <cstdio>
using namespace std;
const int q[5][4]={{2,1,0,2},{1,1,1,1},{0,0,2,1},{0,3,0,0},{1,0,0,1}};
int n,a,b,c,d,f[61][61][61][61];
int dfs(int a,int b,int c,int d){
	if (f[a][b][c][d]) return f[a][b][c][d];//有值说明已经搜过了
	for (int i=0;i<=4;i++)
	if (a-q[i][0]>=0&&b-q[i][1]>=0&&c-q[i][2]>=0&&d-q[i][3]>=0){
		if (dfs(a-q[i][0],b-q[i][1],c-q[i][2],d-q[i][3])==2) return f[a][b][c][d]=1;//如果上一次是另一个人,那么这一次就是这一个人
	}
	return f[a][b][c][d]=2;
}
int main(){
	freopen("j5.in","r",stdin);
	freopen("j5.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++){
	scanf("%d%d%d%d",&a,&b,&c,&d);
	if (dfs(a,b,c,d)==2) puts("Roland");
	else puts("Patrick");
	}
	return 0;
}

然后讲一下非正解的dp(比记搜慢)

#include <cstdio>
#include <algorithm>
using namespace std;
const int q[5][4]={{2,1,0,2},{1,1,1,1},{0,0,2,1},{0,3,0,0},{1,0,0,1}};
int n,a,b,c,d; bool f[61][61][61][61];//假设全是Roland赢
int main(){
	for (int i=0;i<=60;i++)
	for (int j=0;j<=60;j++)
	for (int k=0;k<=60;k++)
	for (int p=0;p<=60;p++)
	for (int x=0;x<6-1;x++)
	if (i-q[x][0]>=0&&j-q[x][1]>=0&&k-q[x][2]>=0&&p-q[x][3]>=0)
	{
	f[i][j][k][p]=1-f[i-q[x][0]][j-q[x][1]][k-q[x][2]][p-q[x][3]];//找到Patrick的方案
	if (f[i][j][k][p]) break;//直接退出
	}
	freopen("j5.in","r",stdin);
	freopen("j5.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++){
	scanf("%d%d%d%d",&a,&b,&c,&d);
	if (!f[a][b][c][d]) puts("Roland");
	else puts("Patrick");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值