您的位置:首页 > 其它

USACO 2.3 分析

2011-02-13 13:55 253 查看
题目一:The Longest Prefix

题目大意:给出一组可以去匹配的字符串,求在给定的字符串中最长可以匹配出的前缀有多长?

算法1:DP

效率:O(200,000*200*10) (实际远远不到)

对于每个位置,去枚举每个字符串,在除去这个串之后的前面的串可以匹配的情况下判断对应的位时候可以匹配,只要有一个可以匹配该位就可以匹配。如果连续遇到不可匹配的数目大于最大可以匹配的长度的时候,就可以退出了。

小经验:用scanf("%c", c)读字符不能跳过回车符和空格

#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
using namespace std;
const
int maxlen = 200000+2;
bool h[maxlen];
char ch[maxlen];
char s[11];
char pri[201][11];
bool check(int nowpos, int i) {
if (strlen(pri[i]) > nowpos || !h[nowpos-strlen(pri[i])]) return false;
for (int k = 0, j = nowpos-strlen(pri[i])+1; k < strlen(pri[i]); k++, j++)
if (pri[i][k] != ch[j]) return false;
return true;
}
void print(int tot_pri) {
for (int i = 0; i < tot_pri; i++)
printf("%s/n", pri[i]);
}
int main(){
freopen("prefix.in", "r", stdin);
freopen("prefix.out", "w", stdout);
int tot_pri = 0, maxs = 0;//maxs record the longest length of the pri
while (true) {
scanf("%s", s);
if (s[0] == '.') break;
memcpy(pri[tot_pri], s, sizeof(s));
tot_pri++;
if (strlen(s) > maxs) maxs = strlen(s);
}
//print(tot_pri);
int len = 0, maxmiss = 0, max = 0;//maxmiss record the longest length which can't compare
char c;
memset(h,0,sizeof(h));
h[0] = 1;
c = getchar();
while (scanf("%c", &c) == 1) {//read success
if (c == '/n') continue;
len++;
ch[len] = c;
bool flag = false;
for (int i = 0; i < tot_pri && !flag; i++) flag = check(len, i);
if (!flag) maxmiss++;
else { maxmiss = 0;max = len;}
if (maxmiss > maxs) break;
h[len] = flag;
}
printf("%d/n", max);
return 0;
}


测试时间:

Test 1: TEST OK [0.000 secs, 3276 KB]
Test 2: TEST OK [0.000 secs, 3276 KB]
Test 3: TEST OK [0.011 secs, 3276 KB]
Test 4: TEST OK [0.022 secs, 3276 KB]
Test 5: TEST OK [0.022 secs, 3276 KB]
Test 6: TEST OK [0.054 secs, 3276 KB]

算法2:Trie(单词查找树)(这种算法好像当时一下子就写出来了,但到现在才知道它的名字)

效率:O(200,000)

题目二:Cow Pedigrees

题目大意:求N个结点高度为K的树的种数

算法:DP

效率:O(NK)

s[i][j] = s[left][h]*s[right][j-1] + s[left][j-1]*s[right][h] + s[left][j-1]*s[right][j-1] 1<=h<=j-2,1<=left, right <i and left + right + 1 = i

优化:满足这种条件的树的节点数一定为奇数;最大高度不会超过(N+1)/2;

#include <stdio.h>
#include <string.h>
int s[100][100];
int main(){
freopen("nocows.in", "r", stdin);
freopen("nocows.out", "w", stdout);
int N, K;
scanf("%d%d", &N, &K);
memset(s,0,sizeof(s));//s[i][j]  i*2+1 nodes of height j
s[0][1] = 1;
if ((N & 1) == 0) printf("0/n"); else {
N = (N-1) >> 1;
for (int i = 1; i <= N; i++) {
int maxh = i+1;
if (K < maxh) maxh = K;
for (int h = 1; h <= maxh; h++)
for (int j = 0; j < i; j++) {
for (int hh = 1; hh < h-1; hh++)
s[i][h] = (s[i][h] + s[j][hh]*s[i-j-1][h-1] + s[i-j-1][hh]*s[j][h-1]) % 9901;
s[i][h] = (s[i][h] + s[j][h-1]*s[i-j-1][h-1]) % 9901;
}
}
printf("%d/n", s
[K]);
}
return 0;
}


题目三:Zero Sum

算法:DFS

注意:算的时候要从左向右算,从右向左算稍麻烦;

#include <stdio.h>
#include <string.h>
int num[10], calc[10];
int n;
void dfs(int depth) {
if (depth == n) {
memset(num,0,sizeof(num));
int len = 0;
num[0] = 1;
for (int i = 1; i < n; i++)
if (calc[i] == 0) num[len] = num[len]*10+(i+1);
else num[++len] = (i+1);
len =0;
for (int i = 1; i < n; i++)
if (calc[i] == 1) {
num[len+1] += num[len];
len++;
} else
if (calc[i] == 2){
num[len+1] = num[len] - num[len+1];
len++;
}
if (num[len] == 0) {
printf("1");
for (int i = 1; i < n; i++) {
if (calc[i] == 0) printf(" "); else
if (calc[i] == 1) printf("+"); else
printf("-");
printf("%d", i+1);
}
printf("/n");
}
return;
}
for (int i = 0; i <= 2; i++) {
calc[depth] = i;
dfs(depth+1);
calc[depth] = 0;
}
}
int main(){
freopen("zerosum.in", "r", stdin);
freopen("zerosum.out", "w", stdout);
scanf("%d", &n);
memset(calc,0,sizeof(calc));
dfs(1);
return 0;
}


题目四:Money Systems

算法:DP 背包

小知识:INT64在DEV-C++的g++编译器中printf("%I64d",n),而在GNU中要写成printf("%lld",n)

#include <stdio.h>
#include <string.h>
long long s[10001];
int main(){
freopen("money.in", "r", stdin);
freopen("money.out", "w", stdout);
int V, N;
scanf("%d%d", &V, &N);
memset(s,0,sizeof(s));
s[0] = 1;
int unit;
for (int i = 0; i < V; i++) {
scanf("%d", &unit);
for (int v = unit; v <=N; v++) s[v] += s[v-unit];
}
printf("%lld/n", s
);
return 0;
}


题目五:Controlling Company

算法:DFS/BFS

关键是要理解题目中的规则

(1)不解释(2)不解释(3)你的控制的公司称为子公司,则子公司的子公司仍然是你的公司,也受你的管辖

这道题实质是图论的题目,可以用邻接表来存贮,哪种搜索随便了。第一条规则在搜索时意味着你先把自己作为本体去拓展

#include <stdio.h>
#include <string.h>
const
int maxn = 101, max = maxn*maxn/2;
int own[maxn];
bool vis[maxn];
int first[maxn], next[max], v[max], w[max];
void dfs(int x) {
if (vis[x]) return;
vis[x] = true;
for (int now = first[x]; now >= 0; now = next[now]) {
own[v[now]] += w[now];
if (own[v[now]] > 50)
dfs(v[now]);
}
}
int main(){
freopen("concom.in", "r", stdin);
freopen("concom.out", "w", stdout);
int n;
scanf("%d", &n);
int m = 0, u;
for (int i = 1; i <= maxn-1; i++) first[i] = -1;
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &u, &v[i], &w[i]);
next[i] = first[u];
first[u] = i;
if (u > m) m = u;
if (v[i] > m) m = v[i];
}
for (int i = 1; i <= m; i++){
memset(own, 0, sizeof(own));
memset(vis, 0, sizeof(vis));
dfs(i);
for (int j = 1; j <= m; j++)
if (own[j] > 50 && i != j)
printf("%d %d/n", i, j);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: