台州學院第七屆“星峰杯”大學生程式設計競賽
阿新 • • 發佈:2019-02-17
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