B 分词
首先建字典树,然后简单dp一下可过,输出有坑!!,因为int没有改成double wa出血。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 26;
const int maxn = 5050;
struct Trie{
double val;
Trie *next[MAX];
};
char s[50], query[maxn];
int fa[maxn];
double dp[maxn];
Trie *root;
void Insert(char *s, double val){
int n = strlen(s);
Trie *pre = root, *cur;
for(int i = 0; i < n; i++){
int id;
if(s[i] >= 'a' && s[i] <= 'z') id = s[i] - 'a';
else id = s[i] - 'A';
if(pre->next[id] == NULL){
cur = new Trie();
cur->val = 0;
for(int j = 0; j < MAX; j++) cur->next[j] = NULL;
pre->next[id] = cur;
}
pre = pre->next[id];
}
pre->val = val;
}
double Find(char *s){
int n = strlen(s);
Trie *pre = root;
for(int i = 0; i < n; i++){
int id;
if(s[i] >= 'a' && s[i] <= 'z') id = s[i] - 'a';
else id = s[i] - 'A';
if(pre->next[id] == NULL) return 0;
pre = pre->next[id];
}
return pre->val;
}
void Delete(Trie *rt){
if(NULL == rt) return;
for(int i = 0; i < MAX; i++)
if(rt->next[i] != NULL) Delete(rt->next[i]);
delete rt;
rt = NULL;
}
double cal(double x){
if(x == 0.0) return 0.0;
else return log(x);
}
void print(int son){
if(son == 0) return ;
print(fa[son]);
for(int i = fa[son]+1; i <= son; i++)
printf("%c", query[i]);
printf(" ");
}
int main(){
int n, m;
while(scanf("%d", &n) != EOF){
root = new Trie();
for(int i = 0; i < MAX; i++) root->next[i] = NULL;
double val;
for(int i = 0; i < n; i++){
scanf("%s %lf", s, &val);
Insert(s, val);
}
scanf("%d", &m);
while(m--){
scanf("%s", query+1);
memset(dp, 0, sizeof(dp));
int len = strlen(query+1);
for(int i = 1; i <= len; i++){
int tot = 0;
for(int j = i; j <= i+30 && j <= len; j++){
s[tot++] = query[j];
s[tot] = '\0';
double result = Find(s);
if(dp[j] < dp[i-1] + (double)tot*tot*cal(result)){
fa[j] = i-1;
dp[j] = dp[i-1] + (double)tot*tot*cal(result);
}
}
}
double MAX = 0;
int flag = 0;
for(int i = 1; i <= len; i++)
if(dp[i] >= MAX){ MAX = dp[i]; flag = i;}
printf("%.6lf\n", MAX);
if(flag == len){
print(fa[flag]);
for(int i = fa[flag]+1; i <= len; i++) printf("%c", query[i]);
printf("\n");
continue;
}
print(flag);
for(int i = flag+1; i <= len; i++) printf("%c", query[i]);
printf("\n");
}
Delete(root);
}
return 0;
}
C 袋鼠妈妈找孩子
非常巧妙地一个深搜,每一个要走的格子,周围最多只能有一格(其实就是走过来的那一格)是走过的。数据量比较小,然后爆搜。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 10;
int dir[4][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};
char maze[maxn][maxn];
int n, m;
int x, y, k;
int judge(int xx, int yy){
if(xx < 1 || xx > n || yy < 1 || yy > m) return false;
return true;
}
bool dfs(int xx, int yy, int t){
int tot = 0;
for(int i = 0; i < 4; i++){
int nx = xx + dir[i][0];
int ny = yy + dir[i][1];
if(judge(nx, ny) && maze[nx][ny] == '.') tot++;
}
if(tot >= 2) return false;
if(xx == x && yy == y){
if(t >= k) return true;
return false;
}
for(int i = 0; i < 4; i++){
int nx = xx + dir[i][0];
int ny = yy + dir[i][1];
if(judge(nx, ny) && maze[nx][ny] == '*'){
maze[nx][ny] = '.';
if(dfs(nx, ny, t+1)) return true;
maze[nx][ny] = '*';
}
}
return false;
}
void init(){
for(int i = 0; i < maxn; i++)
for(int j = 0; j < maxn; j++)
maze[i][j] = '*';
}
int main(){
while(scanf("%d%d", &n, &m) != EOF){
init();
scanf("%d%d%d", &x, &y, &k);
maze[1][1] = '.';
dfs(1, 1, 0);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++)
printf("%c", maze[i][j]);
printf("\n");
}
}
return 0;
}
E 黑心啤酒厂
i÷gcd(x,i)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int gcd(int a, int b){
return !b?a:gcd(b, a%b);
}
int main(){
int x, n;
while(scanf("%d%d", &x, &n) != EOF){
for(int i = 2; i <= n; i++)
printf("%d\n", i/gcd(i, x));
}
return 0;
}
F 丽娃河的狼人传说
按右端点排序,然后贪心的思想,能往右边放就往右边放。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1100;
struct Node{
int l, r, t;
bool operator < (const Node& temp)const{
return r < temp.r;
}
}node[maxn];
int val[maxn];
int main(){
int T;
scanf("%d", &T);
for(int kase = 1; kase <= T; kase++){
memset(val, 0, sizeof(val));
int n, m, k, x;
scanf("%d%d%d", &n, &m, &k);
for(int i = 0; i < k; i++){
scanf("%d", &x);
val[x] = 1;
}
for(int i = 0; i < m; i++)
scanf("%d%d%d", &node[i].l, &node[i].r, &node[i].t);
sort(node, node+m);
int ans = 0, judge = 0;
for(int i = 0; i < m; i++){
int tot = 0;
for(int j = node[i].l ; j <= node[i].r; j++)
if(val[j]) tot++;
if(node[i].r - node[i].l + 1 < node[i].t) {
judge = 1;
break;
}
if(tot >= node[i].t) continue;
else ans += node[i].t-tot;
int temp = node[i].t - tot;
for(int j = node[i].r ; j >= node[i].l; j--)
if(!val[j]){
val[j] = 1;
temp--;
if(temp == 0) break;
}
}
printf("Case %d: ", kase);
if(judge) printf("-1\n");
else printf("%d\n", ans);
}
return 0;
}
G 铁路修复计划
我表示二分的k那么大怎么过的这道题!!二分k然后最小生成树。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const double eps = 1e-7;
const int maxn = 1e5+100;
LL n, m, M;
struct Edge{
int from, to, t, f;
double val;
bool operator < (const Edge& temp)const{
return val < temp.val;
}
}e[maxn];
int fa[maxn];
int Find(int x){
return fa[x] == x?x:fa[x] = Find(fa[x]);
}
bool kruskal(double mid){
for(int i = 0; i < m; i++)
if(e[i].f) e[i].val = mid*e[i].t;
else e[i].val = e[i].t;
sort(e, e+m);
for(int i = 0; i < maxn; i++) fa[i] = i;
double ans = 0;
for(int i = 0; i < m; i++){
int xx = Find(e[i].from);
int yy = Find(e[i].to);
if(xx != yy){
fa[xx] = yy;
ans += e[i].val;
if(ans > M) return false;
}
}
return true;
}
int main(){
while(scanf("%lld%lld%lld", &n, &m, &M) != EOF){
for(int i = 0; i < m; i++)
scanf("%d%d%d%d", &e[i].from, &e[i].to, &e[i].t, &e[i].f);
double l = 1.0, r = 1e15;
while((r-l) > eps){
double mid = (l+r)/2;
if(kruskal(mid)) l = mid;
else r = mid;
}
printf("%.6lf\n", l);
}
return 0;
}