深圳大学2011冬季赛解题报告

排名:http://acm.szu.edu.cn/wiki/index.php/Special:JudgeContestRank

可能这次比赛对平时不太玩的同学有点残忍。

题目难度总体比去年(H47-H50,H53,H57-H61)高一点,少了一个特别的水题。
导致本次1题获奖,然后三等奖没有发完,fb也出得很慢,25分钟,WA两次。
不过蛮高兴的事,蛮多人坚持到最后了,ACM需要坚持。

本次的最高题数是5题,有点可惜。
不算酱油的,19个人过题,有点悲剧。
但还是祝贺一下本次获奖的同学。
同时也感谢一下学生会的支持。

废话不说,解题先

Problem A. Magic Matrix
标签:**题 模拟题
题意:2^k*2^k的方阵分四块,然后重组成2^(k+1)*2^(k-1)的矩阵,直到变成一行。
解法:写个函数move(i,j,ii,jj,size)直接搞应该行,动态内存应该不会超。

Problem B. Simple Count
标签:*题 简单大数
题意:找出[0,m]之间个位是n(0<=n<9)的整数的个数
解法:看最后一位,大于等于n的,不要最后一位然后+1就好,
小于n就直接不要最后一位输出,数据没有前导0,应该不难。

Problem C. Travel Problem
标签:**题 dfs、bfs、并查集
题意:有n个景点,景点有value,景点之间有road,可以在景点之间相互到达,
第一次可以任选一个点,问能获得的value的最大值。
解法:上面三种做法都可以,就找出每个联通分量,然后找最大值即可。

Problem D. Divide apple
标签:**题 排序+索引排序
题意:给n个苹果,按大到小依次分m个人,问最后一个人得到的苹果的序号,序号要求升序。
解法:struct{int size, num,ismine; }这样存就好,第一次按size排序,标ismine(1,0),
然后按ismine,num排序就好。

Problem E. Game
标签:*题 想法题
题意:一个有n个cells的box,每个里面有一些小球,可以间隔m从前往后移动小球,
问第一个状态能不能移到第二个。
解法:本来没有从前往后的,那样间隔求和就好。这个加上从前往后比较就好啦。

Problem F. A Strange Tree
标签:***题 树dp
题意:一棵无向树,每个节点有一些值,拿了这个与他相连都不能拿,问能拿到的最大值。
解法:dfs,等到该节点变黑(出栈)的时候拿孩子孙子节点更新当前节点,
得到以该点为根的最值,然后dfs(1)就是结果。也可以动态更新。也可以先建孩子兄弟树搞。

Problem G. A simple problem with square pattern
标签:****题 线段树 成段更新,点查询
题意:n个3*3的矩阵,m次操作(旋转,翻转或者查询某个节点的矩阵)
解法:线段树,注意到旋转和翻转是有序的,把翻转往后拖,可加点延迟。
这类问题目前好像没有通用解法,方向有:懒操作(统一成一个操作,或者一个操作往后拖),状态压缩。

Problem H. Chinese Zodiac
标签:***题 状态压缩+spfa
题意:12种动物,有n中魔法,每种魔法可以从一个动物状态转到另一个状态,价值是第二个状态的动物数*魔法自身价值。
解法:01标记各种动物在与不在,则有2^12种状态,然后每种魔法当做一条边,spfa之。

Problem I. ABC
标签:**题 bfs
题意:给个类似迷宫的东西,然后有三个人,他们可以到处跑,问最小的会面步数。
解法:对三个人bfs,记录各点最小步数,然后查看vis为3的点的最小值就好。


我只搞了自己的题以及测了益望的题,可能有错,请指正。


后记:感觉蛮好,大一的蛮给力,当然也有悲剧的事以及可惜的事,大家继续加油哈!

然后谢谢两位队员!这套题大家还是花了不少时间的,然后,出题不容易啊!!


最后贴几个代码:

简单题就不贴了

C:Travel

#include <cstdio>
#include <cstring>
#include <cassert>

#define N 1050

int val[N], vis[N], mat[N][N];
int n, max_val, num_val;

void dfs(int x){
	vis[x]=1;	num_val+=val[x];
	for(int i=1; i<=n; ++i) {
		if(mat[x][i] && !vis[i]) 
			dfs(i);
	}
}

int main()
{
	int m, i, u, v, cas=1;

	freopen("in1.txt","r", stdin);
	freopen("ou1.txt","w", stdout);
	
	while(scanf("%d%d", &m, &n) && (m+n)){
		assert(1<=n && n<=1000);
		assert(0<=m && m<=N*N);
		memset(mat, 0, sizeof(mat));
		memset(vis, 0, sizeof(vis));

		for(i=1; i<=n; ++i)	{
			scanf("%d", &val[i]); 
			assert(1<=val[i] && val[i]<=1000);
		}
		
		for(i=0; i<m; ++i)	{
			scanf("%d%d", &u, &v); 
			assert(1<=u && u<=n);
			assert(1<=v && v<=n);
			mat[u][v]=mat[v][u]=1;
		}

		max_val=0;
		for(i=1; i<=n; ++i){
			if(!vis[i]){
				num_val=0;	dfs(i);
				if(max_val<num_val)	max_val=num_val;
			}
		}
		
		printf("Case %d:\n%d\n", cas++, max_val);
	}

	return 0;
}


I:ABC


#include <cstdio>
#include <cstring>
#include <cassert>
#include <cmath>
#include <queue>
#include <iostream>

using namespace std;

#define N 150
#define inf (0x7fffffff)

char mat[N][N], vis[N][N];
struct { int v, x;}ans[N][N];
struct info{ int v, x, y;};
int dx[]={0, 0, 1, -1};
int dy[]={1, -1, 0, 0};
int n;

inline int isok(int x, int y){
	return (0<=x&&x<n && 0<=y&&y<n && !vis[x][y] && mat[x][y]!='#');
}

void bfs(int x, int y){
	info of, nf;
	int i;

	queue<info> q;

	of.v=0; of.x=x; of.y=y;
	q.push(of); vis[of.x][of.y]=1;
	while(!q.empty()){
		of=q.front();
		q.pop();
		
		ans[of.x][of.y].v++;
		ans[of.x][of.y].x+=of.v;

		for(i=0; i<4; ++i){
			nf.x=of.x+dx[i];
			nf.y=of.y+dy[i];
			nf.v=of.v+1; 
			if(isok(nf.x, nf.y)) {
				q.push(nf);		vis[nf.x][nf.y]=1;
			}
		}
	}
}

int main()
{
	int t, i, j;
	int ax, ay, bx, by, cx, cy;

	scanf("%d", &t);
	assert(1<=t && t<=100);
	while(t--) {
		scanf("%d", &n);
		assert(2<=n && n<=100);
		getchar();
		for(i=0; i<n; ++i) gets(mat[i]);

		ax=ay=bx=by=cx=cy=-1;
		for(i=0; i<n; ++i) {
			for(j=0; j<n; ++j) {
				if(mat[i][j]=='#' || mat[i][j]=='.') ;
				else if(mat[i][j]=='A') {
					assert(ax==-1 && ay==-1);
					ax=i; ay=j;
				}
				else if(mat[i][j]=='B') {
					assert(bx==-1 && by==-1);
					bx=i; by=j;
				}
				else if(mat[i][j]=='C') {
					assert(cx==-1 && cy==-1);
					cx=i; cy=j;
				}
				else assert(0>1); // other? wrong
			}
		}

		assert(ax!=-1 && ay!=-1);
		assert(bx!=-1 && by!=-1);
		assert(cx!=-1 && cy!=-1);
		memset(ans, 0, sizeof(ans));

		memset(vis, 0, sizeof(vis));
		bfs(ax, ay);
		memset(vis, 0, sizeof(vis));
		bfs(bx, by);
		memset(vis, 0, sizeof(vis));
		bfs(cx, cy);
		
		int res=inf;
		for(i=0; i<n; ++i) {
			for(j=0; j<n; ++j) {
				assert(0<=ans[i][j].v && ans[i][j].v<=3);
				if(ans[i][j].v==3 && res>ans[i][j].x)
					res=ans[i][j].x;
			}
		}
		printf("%d\n", res==inf?-1:res);
	}
	return 0;
}



F:Strange Tree

#include <cstdio>
#include <cstring>
#include <cassert>
#include <cmath>
#include <vector>
#include <algorithm>
#include <iostream>


using namespace std;


#define max(a, b) (a>b?a:b)
#define N 100000


vector<int> m[N];	// mat
int s[N], ss[N], d[N], v[N], a[N];
// son grandson dp vis data


void dfs(int r){
	d[r]=s[r]=ss[r]=0;
	
	v[r]=1;	// 0 white 1 grey 2 black
	for(int i=0; i<m[r].size(); ++i){
		if(!v[m[r][i]]) dfs(m[r][i]);
	}
	
	for(i=0; i<m[r].size(); ++i)
	{
		if(v[m[r][i]]==2) {
			s[r]+=d[m[r][i]];			
			for(int j=0; j<m[m[r][i]].size(); ++j) {
				ss[r]+=d[m[m[r][i]][j]];
			}
		}
	}


	v[r]=2;
	d[r]=max(s[r],ss[r]+a[r]);
}


int main()
{
	int t, n, i;

	scanf("%d", &t);
	assert(2<=t && t<=100);
	while(t--) {
		memset(v, 0, sizeof(v));
		memset(a, 0, sizeof(a));
		for(i=0; i<N; ++i) m[i].clear();


		scanf("%d", &n);
		assert(2<=n && n<=10000);
		for(i=1; i<=n; ++i) {
			scanf("%d", &a[i]);
			assert(a[i]<100);
		}


		int u, v;
		for(i=1; i<n; ++i) {
			scanf("%d%d", &u, &v);
			assert(1<=u && u<=n);
			assert(1<=v && v<=n);
			m[u].push_back(v);
			m[v].push_back(u);
		}


		dfs(1);
		printf("%d\n", d[1]);
	}
	return 0;
}


H: Chinese Zodiac

#include <cstdio>
#include <cstring>
#include <cassert>
#include <vector>
#include <stack>
#include <iostream>

using namespace std;

#define LL(x) (1<<(x))
#define N (1<<12)
#define inf (0x7ffffff)

struct edge{
	int t, v;
};

vector<edge> mat[N];
stack<int> mst;
int shor[N], ins[N], cas=1;

inline void init() {
	for(int i=0; i<N; ++i) { 
		ins[i]=0;
		shor[i]=inf;	
		mat[i].clear();	
	}
}

inline void input() {
	edge tmp;
	int i, j, m, es, ee, ev, f, x;

	scanf("%d", &m);
	for(i=0; i<m; ++i){
		scanf("%d%d%d", &es, &ee, &ev);
		f=tmp.t=tmp.v=0;
		for(j=0; j<es; ++j){
			scanf("%d", &x);
			f+=LL(x-1);
		}
		for(j=0; j<ee; ++j){
			scanf("%d", &x);
			tmp.t+=LL(x-1);
		}
		tmp.v=ev*ee;
		mat[f].push_back(tmp);
//		printf("%d %d %d\n", f, tmp.t, tmp.v);
	}
}

inline void solve(){
	int u, v, i;

	while(!mst.empty()) mst.pop();
	mst.push(0); ins[0]=1; shor[0]=0;
	while(!mst.empty()){
		u=mst.top(); mst.pop();
		ins[u]=0;
		for(i=0; i<mat[u].size(); ++i){
			v=mat[u][i].t;
			if(shor[v]>shor[u]+mat[u][i].v) {
				shor[v]=shor[u]+mat[u][i].v;
				if(!ins[v]) {
					mst.push(v); ins[v]=1;
				}
			}
		}
	}
	
	printf("Case %d:\n%d\n", cas++, shor[4095]==inf?-1:shor[4095]);
}

int main()
{
	int t;

	freopen("ou5.txt","w", stdout);
	freopen("in5.txt","r", stdin);

	scanf("%d", &t);
	while(t--){
		init();	
		input();
		solve();
	}

	return 0;
}


G:A Simple problem with square pattern

#include <stdio.h>
#include <string.h>
#include <assert.h>
 
 
#define N 50050
#define LL L, m, c<<1
#define RR m+1, R, c<<1|1
#define swap(a,b) a^=b^=a^=b
 
/*
trans
4 1 <=> 3 4
4 2 <=> 2 4
4 3 <=> 1 4
*/
 
char mt[N][5][5];// matrix
int rt[N<<2]={0}, ft[N<<2]={0};
// rotate reflect 
 
void rot(int x);
void ref(int x);
void update(int c, int x);
void build(int L, int R, int c);
void pushDown(int L, int R, int c);
void ques(int p, int L, int R, int c);
void insert(int l, int r, int v, int L, int R, int c);
 
int main()
{
	int n, q, a, b, c;
 
	scanf("%d%d", &n, &q);
	assert(1<=n && n<=N);
	assert(1<=q && q<=N<<1);
	build(1, n, 1);
	while(q--){
		char ch[2];
		scanf("%s", ch);
		if(*ch=='C') {
			scanf("%d%d%d", &a, &b, &c);
			assert(1<=a && a<=N);
			assert(1<=b && b<=N);
			assert(1<=c && c<=4);
			assert(a<=b);
			insert(a, b, c, 1, n, 1);
		}
		else if(*ch=='Q') {
			scanf("%d", &a);
			assert(1<=a && a<=N);
			ques(a, 1, n, 1);			
		}
		else assert(0>1);
	}
 
	return 0;
}
 
 
// clock 90
void rot(int x){
	int i, j;
 
	for(i=0; i<3; ++i){
		for(j=0; j<3; ++j){
			mt[0][i][j]=mt[x][i][j];
		}
	}
 
	for(i=0; i<3; ++i){
		for(j=0; j<3; ++j){
			mt[x][i][j]=mt[0][2-j][i];
		}
	}
}
 
// left right
void ref(int x){
	for(int i=0; i<3; ++i){
		swap(mt[x][i][0], mt[x][i][2]);
	}
}
 
// operating
void update(int c, int x){
	rt[c]%=4; while(rt[c]--) rot(x);
	while(ft[c]--) ref(x);
	rt[c]=ft[c]=0;
}
 
// seg build
void build(int L, int R, int c)
{
	if(L==R) { 
		for(int i=0; i<3; ++i)	
			scanf("%s", mt[L][i]);
		return; 
	}
	int m=(L+R)>>1;
	build(LL);
	build(RR);
}
 
// pushDown just once
void pushDown(int L, int R, int c){
	int m=(L+R)>>1;	
	rt[c]%=4;
	if(rt[c]){		
		insert(L, m, rt[c], LL);
		insert(m+1, R, rt[c], RR);
	}
	if(ft[c]){
		insert(L, m, 4, LL);
		insert(m+1, R, 4, RR);
	}
	rt[c]=ft[c]=0;
}
 
// seg insert
void insert(int l, int r, int v, int L, int R, int c)
{
	if(l<=L && R<=r){ 
		if(v==1||v==2||v==3) rt[c]+=ft[c]?(4-v):v;
		else if(v=4) ft[c]=ft[c]?0:1;
		else assert(0>1);
		return; 
	}
 
	pushDown(L, R, c);
 
	int m=(L+R)>>1;
	if(l<=m) insert(l, r, v, LL);
	if(r>m) insert(l, r, v, RR);
}
 
 
// point value
void ques(int p, int L, int R, int c)
{
	if(L==R) {
		update(c, L);
		for(int i=0; i<3; ++i)
			puts(mt[L][i]);
		return;
	}
 
	pushDown(L, R, c);
 
	int m=(L+R)>>1;
	if(p<=m) ques(p, LL);
	else ques(p, RR);
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值