1. 程式人生 > >台州學院第七屆“星峰杯”大學生程式設計競賽

台州學院第七屆“星峰杯”大學生程式設計競賽

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

#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個城市的一半

二分 + 深搜

#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