台州学院第七届“星峰杯”大学生程序设计竞赛

4:3

谁是冠军?

floyd + 打印路径 以前一模一样的做到过 有木有 所以不解释了

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <string>
#include <queue>
#include <stack>
using namespace std;

int a[500][500];
int map[500][500];
const int inf = 100000000;
int n;
void floyd()
{
	int k,i,j;
	for(k = 1;k <= n; k++)
	{
		for(i = 1;i <= n; i++)
		{
			for(j = 1;j <= n; j++)
			{
				if(a[i][k] + a[k][j] < a[i][j])
				{
					a[i][j] = a[i][k]  + a[k][j];
					map[i][j] = map[i][k];
				}
				else if(a[i][k] + a[k][j] == a[i][j])
				{
					if(map[i][j] > map[i][k] && i != k)
					{
						map[i][j] = map[i][k];
					}
				}
			}
		}
	}
}
int main()
{
	int i,j,m;
	while(scanf("%d",&n),n)
	{
		for(i = 1;i <= n; i++)
		{
			for(j = 1;j <= n; j++)
			{
				if(i == j)
				{
					a[i][j] = 0;
					map[i][j] = j;
				}
				else
				{
					a[i][j] = inf;
					map[i][j] = j;
				}
			}
		}
		for(i = 1;i <= n; i++)
		{
			scanf("%d",&m);
			while(m--)
			{
				scanf("%d",&j);
				a[i][j] = 1;
				map[i][j] = j;
			}
		}
		floyd();
		scanf("%d",&m);
		while(m--)
		{
			int x,y,k;
			scanf("%d %d",&x,&y);
			
			if(a[x][y] == inf)
				printf("%d<%d",x,y);
			else
			{
				printf("%d beats %d in %d times: %d",x,y,a[x][y],x);
				k = x;
				int cnt = 0;
				while(k != y)
				{
					//cnt++;
					//if(cnt > 10)
					//	break;
					k = map[k][y];
					printf(">%d",k);
				}
			}
			puts("");
		}
		puts("");
	}
	return 0;
}

 

滚动特效

回文数列

LCS 转换成LIS

a数组数输入的

b数组是a的逆序

例如 a 1 1 2 2 b 2 2 1 1

首先因为每个数小于100

对于a数组每个数  找到b对应的位置 所以 1 对应  3 4 (b数组的1在3 和 4 的位置) 2 对应1 2

然后a数组就变成了 4 3 4 3 2 1 2 1 (每个数对应的位置要倒过来  比赛的时候没倒过来就错了 唉)

对新的 数组做对应的LIS即可 用2分求出LIS

学习自http://www.th7.cn/Program/cp/201208/88055.shtml

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>

using namespace std;
int a[20010];
int b[20010];
int dp[4000010];
int n;
int c[4000010];
int map[210];

void get()
{
	int j,k,i;
	vector <int> v[10010];
	for(i = 0;i <= 200; i++)
	{
		if(map[i])
		{
			for(j = 1;j <= n; j++)
			{
				if(b[j] == i)
					v[i].push_back(j);
			}
		}
	}
	k = 1;
	for(i = 1;i <= n; i++)
	{
		int len = v[a[i]].size();
		for(j = len - 1;j >= 0; j--)
		{
			c[k++] = v[a[i]][j];
		}
	}
	//for(i = 1;i < k; i++)
	//	printf("%d ",c[i]);
	//puts("");
	int l ,r;
	dp[1] = c[1];
	int len = 1;
	for(i = 2;i < k; i++)
	{
		l = 1;
		r = len;
		while(l <= r)
		{
			int m = (l + r) >> 1;
			if(dp[m] < c[i])
				l = m  + 1;
			else
				r = m  - 1;
		}
		if(len < l)
			len++;
		dp[l] = c[i];
	}
	printf("%d\n",n - len);
}
int main()
{
	int t,i,j;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		memset(map,0,sizeof(map));
		for(i = 1;i <= n; i++)
		{
			scanf("%d",&a[i]);
			map[a[i]] = 1; 
		}
		for(i = 1,j = n;i <= n; i++,j--)
		{
			b[j] = a[i];
		}

		get();
	}
	return 0;
}

 

My Trim Function

手机上网流量

计算面积

Poker Solitaire Game

发了发了

Jumping Castle

题目已经改了 走到下一个要消耗 2个城市差的绝对值的体力 求最小多少体力可以走完n*n个城市的一半

二分 + 深搜

参考http://www.cnblogs.com/luotinghao/p/3446330.html

差不多的给一题 http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=4310

#include <stdio.h>
#include <string.h>
#include <math.h>
int n,flag,count;
int a[110][110];
int vis[110][110];
int dir[4][2] = {1,0,0,1,-1,0,0,-1};
int max;
void dfs(int x,int y,int m)
{
	
	if(count * 2 >= n*n)
	{
		flag = 1;
		return;
	}
	int i,xx,yy;
	for(i = 0;i < 4; i++)
	{
		xx = x + dir[i][0];
		yy = y + dir[i][1];
		if(xx >= 1 && xx <= n && yy >= 1 && yy <= n && !vis[xx][yy] && (int)fabs(a[xx][yy] - a[x][y]) <= m)
		{
			count++;
			vis[xx][yy] = 1;
			dfs(xx,yy,m);
		}
	}
}

bool check(int m)
{
	int i,j,k;
	flag = 0;
	memset(vis,0,sizeof(vis));
	for(j = 1; j <= n; j++)
	{
		for(k = 1;k <= n; k++)
		{
			if(!vis[j][k])
			{
				count = 1;
				vis[j][k] = 1;
				dfs(j,k,m);
			}
			if(flag)
				return true;
		}	
	}
	return false;
}
		
int erfen(int l,int r)
{
	int m;
	while(l < r)
	{
		m = (l + r) >> 1;
		if(check(m))
			r = m;
		else
			l = m + 1;
	}
	return r;
}
int main()
{
	int i,j;
	while(scanf("%d",&n)!=EOF)
	{
		max = 0;
		for(i = 1;i <= n; i++)
		{
			for(j = 1;j <= n; j++)
			{
				scanf("%d",&a[i][j]);
				if(max < a[i][j])
					max = a[i][j];
			}
		}
		printf("%d\n",erfen(0,max));
	}
	return 0;
}


 

The Longest Indentical Sub-String

后缀数组基本运用 求出后缀数组 和 LCP 在RMQ查询即可 查询线段树 或者ST

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
using namespace std;
const int MAXN = 100010;

int sa[MAXN];
int t[MAXN],t2[MAXN],c[MAXN];
int rank[MAXN],height[MAXN];
int dp[MAXN][100];
void RMQ_init(int n)
{

	int i,j,k;
	for(i = 0; i < n; i++)
		dp[i][0] = height[i+1];
	k = (int) (log((double)n + 0.2) / log(2.0));
	for(j = 1; j <= k; j++)
		for(i = 0; i + (1 << j) - 1 <= n; i++)
			dp[i][j] = min(dp[i][j-1],dp[i + (1 << (j-1))][j-1]);
}

int RMQ(int l,int r)
{
	int k = 0;
	k = (int) (log((double)(r - l + 1 + 0.2)) / log(2.0));
	return min(dp[l][k],dp[r-(1<<k)+1][k]);
}
void build_sa(char *s,int n,int m)//倍增算法 
{
	int i,*x = t,*y = t2;
	//基数排序
	for(i = 0; i < m; i++)
		c[i] = 0;
	for(i = 0; i < n; i++)
		c[x[i] = s[i]]++;
	for(i = 1; i < m; i++)
		c[i] += c[i-1];
	for(i = n-1; i >= 0; i--)
		sa[--c[x[i]]] = i;
	for(int k = 1; k <= n; k <<= 1)
	{
		int p = 0;
		//直接利用sa数组排序第二关键字
		for(i = n-k; i < n; i++)
			y[p++] = i;
		for(i = 0; i < n; i++)
			if(sa[i] >= k)
				y[p++] = sa[i] - k;
		//基数排序第一关键字
		for(i = 0; i < m; i++)
			c[i] = 0;
		for(i = 0; i < n; i++)
			c[x[y[i]]]++;
		for(i = 0; i < m; i++)
			c[i]+= c[i-1];
		for(i = n-1; i >= 0; i--)
			sa[--c[x[y[i]]]] = y[i];
		//根据sa和y数组计算新的x数组
		swap(x,y);
		p = 1; x[sa[0]] = 0;
		for(i = 1;i < n; i++)
			x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1:p++;
		if(p >= n)
			break;
		m = p;
	}
}

void getHeight(char *s,int n)
{
	int i,j,k = 0;
	for(i = 1; i <= n; i++)
		rank[sa[i]] = i;
	for(i = 0; i < n; i++)
	{
		if(k)
			k--;
		int j = sa[rank[i]-1];
		while(s[i+k] == s[j+k])
			k++;
		height[rank[i]] = k;
	}
}
int main()
{
	char s[MAXN];
	int p1,p2,m,n,i,k;
	while(gets(s))
	{
		n = strlen(s);
		if(!n)
			continue;
		build_sa(s,n+1,200);
		scanf("%d",&m);
		getHeight(s,n);
		RMQ_init(n);
		while(m--)
		{
			scanf("%d %d",&p1,&p2);
			if(rank[p1] > rank[p2])
				swap(p1,p2);
			printf("%d\n",RMQ(rank[p1],rank[p2]-1));
		
		}
	}
	return 0;
}


 

A VS B

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值