标签:priority ble 自动机 nod ali ++ long 足球 math
A.机器人足球
模拟
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
double dis(int x1, int y1, int x2, int y2) {
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main() {
int x, y;
scanf("%d%d", &x, &y);
double d = dis(x,y,100,10)-10;
printf("%.3lf\n",max(d,0.));
}
B.纸牌识别
模拟
#include <iostream>
#include <cstdio>
#include <set>
using namespace std;
typedef pair<int,int> pii;
char x;
int y;
int a[200];
set<pii> s;
int main() {
a[‘P‘]=a[‘K‘]=a[‘H‘]=a[‘T‘]=13;
while (~scanf(" %c%d", &x, &y)) {
if (s.count(pii(x,y))) return puts("GRESKA"),0;
s.insert(pii(x,y));
--a[x];
}
printf("%d %d %d %d\n",a[‘P‘],a[‘K‘],a[‘H‘],a[‘T‘]);
}
C. 卡牌对决
贪心, 前$\fac{n}{2}$场尽量取最大, 后$\frac{n}{2}$场尽量取最小.
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <set>
#define REP(i,a,n) for(int i=a;i<=n;++i)
using namespace std;
const int N = 1e5+10;
int n, a[N];
set<int> Bob, Alice;
int main() {
scanf("%d", &n);
REP(i,1,n) {
scanf("%d",a+i);
Bob.insert(a[i]);
}
REP(i,1,2*n) if (!Bob.count(i)) Alice.insert(i);
int ans = 0;
sort(a+1,a+1+n/2,greater<int>());
REP(i,1,n/2) {
int x = *(--Alice.end());
if (x>a[i]) ++ans, Alice.erase(x);
}
sort(a+1+n/2,a+1+n);
REP(i,1,n/2) {
int x = *Alice.begin();
if (x<a[i]) ++ans, Alice.erase(x);
}
printf("%d\n", ans);
}
D. 自驾游
先跑2次dijkstra求出$N$到每个点最短路, 再建图跑一次dijkstra求出$1->N$最短路即为最少花费.
#include <iostream>
#include <cstdio>
#include <queue>
#include <string.h>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define pb push_back
using namespace std;
typedef long long ll;
const int N = 5e4+10;
int n, m;
struct _ {int to,w;};
vector<_> g1[N], g2[N], g3[N];
ll d1[N], d2[N], d3[N];
int vis[N], u[N], v[N], p[N], q[N];
struct node {
int id;
ll w;
bool operator < (const node &rhs) const {
return w>rhs.w;
}
};
priority_queue<node> pq;
void dij(vector<_> g[], ll d[], int s) {
memset(d,0x3f,sizeof d1);
memset(vis,0,sizeof vis);
pq.push({s,d[s]=0});
while (pq.size()) {
int u = pq.top().id; pq.pop();
if (vis[u]) continue;
vis[u] = 1;
for (auto &e:g[u]) {
ll dd = e.w+d[u];
if (dd<d[e.to]) pq.push({e.to,d[e.to]=dd});
}
}
}
int main() {
scanf("%d%d", &n, &m);
REP(i,1,m) {
scanf("%d%d%d%d", u+i, v+i, p+i, q+i);
g1[v[i]].pb({u[i],p[i]});
g2[v[i]].pb({u[i],q[i]});
}
dij(g1,d1,n);
dij(g2,d2,n);
REP(i,1,m) {
int c = 0;
if (d1[v[i]]+p[i]>d1[u[i]]) ++c;
if (d2[v[i]]+q[i]>d2[u[i]]) ++c;
g3[u[i]].pb({v[i],c});
}
dij(g3,d3,1);
printf("%lld\n", d3[n]);
}
G. 括号序列
$dp$求出长为$x$, 左括号比右括号多$y$个时的方案数. 然后从前往后枚举, 若放‘(‘的方案数不少于$k$, 则放‘(‘, 否则放‘)‘.
注意方案数是指数级, 会爆long long.
#include <iostream>
#define REP(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef long long ll;
const int N = 2010;
int n, k;
ll f[N][N];
char ans[N];
int main() {
scanf("%d%d", &n, &k);
f[0][0] = 1;
ll INF = 1e18+10;
REP(i,1,n) REP(j,0,n) if (f[i-1][j]) {
f[i][j+1] += f[i-1][j];
if (j) f[i][j-1] += f[i-1][j];
f[i][j+1] = min(f[i][j+1], INF);
f[i][j-1] = min(f[i][j-1], INF);
}
int now = 0;
REP(i,1,n) {
if (f[n-i][now+1]>=k) ans[i]=‘(‘,++now;
else ans[i]=‘)‘,k-=f[n-i][now+1],--now;
}
puts(ans+1);
}
H. 不要回文
大回文一定包含小回文, 只用判断长为2和3的回文即可.
#include <iostream>
#include <cstdio>
#include <string.h>
#define REP(i,a,n) for(int i=a;i<=n;++i)
using namespace std;
const int N = 1e6+10;
int n, a[N];
char s[N];
int main() {
scanf("%s", s+1);
n = strlen(s+1);
REP(i,1,n) a[i]=s[i];
int ans = 0, cur = 0;
REP(i,1,n) {
if (a[i]==a[i-1]) ++ans,a[i]=--cur;
if (i>=2&&a[i]==a[i-2]) ++ans,a[i]=--cur;
}
printf("%d\n", ans);
}
I. 你的名字
判断一个串是否是另一个串的子序列, 二分$O(nlogn)$, 或者序列自动机$O(n\Sigma)$
标签:priority ble 自动机 nod ali ++ long 足球 math
原文地址:https://www.cnblogs.com/uid001/p/10987668.html