A、川川教练的困惑
若要找到三个能力值之和大于m,并且最大使得能力值之和最大,可以直接找到能力值最大的三者,求和后再和m比较是否满足条件即可。
#include<cstdio>
#include<algorithm>
using namespace std;
int a[10];
int main() {
int n, m, x;
// freopen("7.in", "r", stdin);
// freopen("7.out", "w", stdout);
scanf("%d %d", &n, &m);
for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
sort(a, a + n);
x = a[n - 1] + a[n - 2] + a[n - 3];
if(x > m) printf("%d\n", x);
else printf("Waiver!\n");
return 0;
}
B、都说小镇的切糕贵
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<string>
#include<climits>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int maxn = 1e5 + 5;
map<char, int> mp;
int main(){
int n;
char s[maxn];
while(~scanf("%d", &n)){
mp.clear();
scanf("%s", s + 1);
for(int i = 1; i <= n; i++){
mp[s[i]]++;
}
int num = mp.size();
int ans = n;
int l = 1, r = 1;
int now = num;
mp.clear();
while(mp.size() != num){
mp[s[r]]++;
r++;
}
r--;
while(l <= n - num + 1 && r <= n){
if(now == num){
ans = min(ans, r - l + 1);
mp[s[l]]--;
if(mp[s[l]] == 0) now--;
l++;
}
if(now < num){
r++;
if(mp[s[r]] == 0) now++;
mp[s[r]]++;
}
}
printf("%d\n", ans);
}
}
C、Guard the empire
题意:
给出n头骨龙的坐标(只会在第一、第二象限),在X轴上放置武器,每个武器都有相同的固定打击范围D,问最少需要多少武器可以将所有骨龙覆盖,如果不能覆盖所有骨龙则输出-1.
思路:
贪心。要求武器的打击范围能够覆盖所有骨龙,若可以覆盖,则以每头骨龙的坐标为圆心,以D为半径,必定与X轴相交与2个可以重合的点。将武器放置在两点间的任意一处都可以覆盖到此骨龙,因此计算出所有骨龙与X轴相交的两个点,按照左端点(或右端点)排序,遍历所有骨龙,判断最右边的武器是否能够覆盖当前遍历到的骨龙,如果不能覆盖,则添置一个新武器于当前骨龙与X轴交点的最右端。
#include<cstdio>
#include<cmath>
#include<string>
#include<iostream>
#include<algorithm>
#define l first
#define r second
#define Pff pair<float, float>
using namespace std;
const int maxn = 1e3 + 5;
int n;
float d;
Pff P[maxn];
int ans;
inline void cal(int &x, int &y, int &i){
P[i].l = (float)x - sqrt(d * d - y * y);
P[i].r = (float)x + sqrt(d * d - y * y);
}
inline void work(){
sort(P + 1, P + 1 + n);
float now = P[1].r;
ans = 1;
for(int i = 2; i <= n; ++i){
if(P[i].l > now){
++ans;
now = P[i].r;
}
else{
if(P[i].r < now) now = P[i].r;
}
}
printf("%d\n", ans);
}
int main(){
int cast = 1;
while(~scanf("%d %f", &n, &d) && n && d){
bool flag = 0;
int x, y;
for(int i = 1; i <= n; ++i){
scanf(" %d %d", &x, &y);
if(d < y|| flag) {
flag = 1;
continue;
}
cal(x, y, i);
}
printf("Case %d: ", cast++);
if(flag) printf("-1\n");
else work();
}
return 0;
}
D、kth的自拍照
int main(){
int n;scanf("%d",&n);
for(int i = 1 ; i <= n ; i++){
for(int j = 1 ; j <= n ; j++){
scanf("%d",&a[i][j]);
}
}
for(int i = 1 ; i <= n ; i++){
for(int j = n ; j >= 1 ; j--){
printf("%d ",a[j][i]);
}
printf("\n");
}
}
//(1,1) -> (1,n)
//(1,n) -> (n,n)
//(n,n) -> (n,1)
//(n,1) -> (1,1)
E、HJ又种花啦
签到题,很容易想到 k >= 2 任何时候都是满足的,只需要特判一种情况:n = 1 && m = 1的时候,k=1也满足情况。
#include<iostream>
using namespace std;
int main()
{
int n, m, k; cin >> n >> m >> k;
if(n + m == 2 || k >= 2) cout << "Beautiful flowers!" << endl;
else cout << "Oh! My poor HJ!" << endl;
return 0;
}
F、Incompetent Fury of a Single Dog
int n;
char s[MaxN];
string ans;
bool vis[30];
int main()
{
cin >> n;
scanf(" %s",&s);
int len = strlen(s);
for(int i = 0; i < len; i++){
if(vis[s[i]-'a'])continue;
else {
vis[s[i]-'a'] = 1;
ans += s[i];
}
}
printf("%d\n",ans.length());
cout << ans << endl;
return 0;
}
G、We are singers
题解:首先将读音和简谱利用Map建立映射关系,在读入读音的过程中通过先前建立的映射判断读音是否正确,错误计数即可。
参考代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 5;
int n, ans, Nmn[maxn];
map<string, int> mp;
string now, pro[8] = {"", "do", "re", "mi", "fa", "sol", "la", "si"};
int main() {
cin >> n;
for(int i = 1; i <= 7; ++i) mp[pro[i]] = i;
for(int i = 1; i <= n; ++i) cin >> Nmn[i];
for(int i = 1; i <= n; ++i) {
cin >> now;
ans += mp[now] != Nmn[i];
}
cout << ans << endl;
return 0;
}
H、Magic necklace
数据范围最大就到n = 11,dfs爆搜即可得到答案,由于题面是多组,需要预处理出答案以免TLE。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,Ans,t;
int vis[105],ans[15];
void dfs(int cur,int fa,int cnt,int x){
if(cnt == x && cur != 2){
Ans++;
return ;
}
else if(cnt == x) return;
for(int i = 1;i <= x; i++){
if(vis[i]) continue;
if(i == fa || i == cur) continue;
if(abs(i - cur) == 1) continue;
vis[i] = 1;
dfs(i,cur,cnt + 1,x);
vis[i] = 0;
}
}
void init(int x){
for(int i = 1;i <= n; i++) vis[i] = 0;
vis[1] = 1;
Ans = 0;
dfs(1,0,1,x);
ans[x] = Ans / 2;
}
int main()
{
for(int i = 1;i <= 11; i++) init(i);
ans[1] = 1;
ans[0] = 0;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
printf("%d\n",ans[n]);
}
}
另外,你也可以用next_permutation函数:
int nums[20], ans[20];
int main()
{
for(int n = 1; n <= 11; n++){
for(int i = 1; i <= n; i++) nums[i] = i;
int cnt = 0;
do{
nums[n+1] = nums[1];
bool f = 0;
for(int i = 1; i <= n; i++) if(abs(nums[i] - nums[i+1]) == 1) { f = 1; break; }
if(!f) cnt++;
}while(next_permutation(nums + 1, nums + n + 1));
ans[n] = cnt / n / 2;
}
ans[1] = 1;
int T; scanf("%d", &T);
while(T--){
int n; scanf("%d", &n);
printf("%d\n", ans[n]);
}
return 0;
}
I、恋爱之子
N2暴力枚举线段是否相交,将相交的线段用并查集维护,最后集合的个数就是答案。或者建图跑搜索也可以。
标程:
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define db double
#define gcd __gcd
#define pb push_back
#define lowbit(x) (x & (-x))
#define PII pair<int, int>
#define all(x) x.begin(), x.end()
#define debug(x) cout << #x << " = " << x << endl
#define rep(i, a, b) for(__typeof(b) i = a; i <= (b); i++)
#define Rep(i, a, b) for(__typeof(a) i = a; i >= (b); i--)
#define Mod(a,b) a<b?a:a%b+b
template<class T> inline T qmin(T a, T b) { return a < b ? a : b; }
template<class T> inline T qmax(T a, T b) { return a > b ? a : b; }
typedef long long ll;
typedef unsigned long long ull;
const db PI = acos(-1);
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 1;
const int maxn = (int)1e5 + 5;//remember to modify it, No RE&nbs***bsp;MLE
const ll INF = 0x3f3f3f3f3f3f3f3f;
using namespace std;
#define cross(p1, p2, p3) ((p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y))
#define cross0p(p1, p2, p3) sign(cross(p1,p2,p3))
const db eps = 1e-9;
inline int sign(db a) { return a < -eps ? -1: a > eps; }
inline int cmp(db a, db b) { return sign(a-b); }
struct P{
db x, y;
P() {}
P(db _x, db _y): x(_x), y(_y) {}
P operator+(P p) { return {x + p.x, y + p.y}; }
P operator-(P p) { return {x - p.x, y - p.y}; }
P operator*(db d) { return {x * d, y * d}; }
P operator/(db d) { return {x / d, y / d}; }
bool operator<(P p)const {
int c = cmp(x, p.x);
if(c) return c == -1;
return cmp(y, p.y) == -1;
}
bool operator==(P o) const {
return cmp(x, o.x) == 0 && cmp(y, o.y) == 0;
}
db distTo(P p) { return (*this - p).abs(); }
db abs() { return sqrt(abs2()); }
db abs2() { return x * x + y * y; }
db dot(P p) { return x * p.x + y * p.y; }
db det(P p) { return x * p.y - y * p.x; }
};
bool intersect(db l1, db r1, db l2, db r2)
{
if(l1 > r1)swap(l1, r1); if(l2 > r2) swap(l2, r2);
return !( cmp(r1, l2) == -1 || cmp(r2, l1) == -1);
}
bool isSS(P p1, P p2, P q1, P q2){
return intersect(p1.x, p2.x, q1.x, q2.x) && intersect(p1.y, p2.y, q1.y, q2.y) && cross0p(p1, p2, q1) * cross0p(p1, p2, q2) <= 0 && cross0p(q1, q2, p1) * cross0p(q1, q2, p2) <= 0;
}
int f[maxn];
int find(int x)
{
if(f[x] == x)return x;
return f[x] = find(f[x]);
}
void Union(int x, int y)
{
int fx = find(x), fy = find(y);
if(fx != fy)f[fx] = fy;
}
int main()
{
int n;
P p[10005], q[10005];
scanf("%d", &n);
for(int i = 1 ; i <= n ; i++){
f[i] = i;
scanf("%lf %lf %lf %lf", &p[i].x, &p[i].y, &q[i].x, &q[i].y);
}
for(int i = 1 ; i <= n ; i++){
for(int j = i + 1 ; j <= n ; j++){
if(isSS(p[i], q[i], p[j], q[j]))Union(i, j);
}
}
int ans = 0;
for(int i = 1 ; i <= n ; i++)if(f[i] == i)ans++;
printf("%d\n", ans);
return 0;
}
J、敢敢单单的斐波那契数列
本题考查对空间滚动的理解与掌握,如果直接开maxn个空间的Int数组,显然有很多空间是浪费的,本题只需要开3个int重复使用即可。
Std:
const int mod = (int)1e9 + 7;
int main()
{
int n; while(~scanf("%d",&n)){
int x = 1, y = 1, ans = 1;
for(int i = 3; i <= n; i++){
ans = x + y;
x = y;
y = ans;
if(x >= mod) x -= mod;
if(y >= mod) y -= mod;
if(ans >= mod) ans -= mod;
}
printf("%d\n",ans);
}
return 0;
}
K、集训队的依赖关系
本题考察对基本树形依赖背包的掌握。
首先可以确定如果存在一个环S,那么指向S里任意一个元素的人我们都不会选择
那么考虑除开这些环还剩下什么,很显然就是一片森林
那么做法就很显然了:直接对于森林中的每一棵树单独考虑进行背包就好了,但是这样不太好写,所以我们可以建一个虚根,虚根的点权为0,对森林中每棵树的根都和这个虚根连一条边,那么现在问题就变成了以虚根为根的一棵树,让你在上面跑一个树形依赖背包就好啦
Std:
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = (int)5e3 + 5;//remember to modify it, No RE&nbs***bsp;MLE
ll dp[maxn][maxn];
int n, m, S;
ll val[maxn];
bool vis[maxn];
vector<int> G[maxn];
int cost[maxn], ind[maxn];
void dfs(int u, int sum){
int Min;
for(int v : G[u]){
Min = sum + cost[v];
if(Min <= S) {
for(int j = 0; j < Min; ++j) dp[v][j] = -INF;
for(int j = S; j >= Min; --j) dp[v][j] = dp[u][j - cost[v]] + val[v];
dfs(v, Min);
for(int j = 0; j <= S; ++j) dp[u][j] = max(dp[u][j], dp[v][j]);
}
}
return ;
}
int main()
{
scanf("%d %d %d", &n, &S, &m);
for(int i = 1; i <= n; i++) scanf("%d", val + i);
for(int i = 1; i <= n; i++) scanf("%d", cost + i);
for(int i = 1; i <= m; i++){
int u, v; scanf("%d %d", &u, &v);
G[v].push_back(u);
++ind[u];
}
for(int i = 1; i <= n; i++) if(ind[i] == 0) G[0].push_back(i);
dfs(0, 0);
printf("%lld\n", dp[0][S]);
return 0;
}
L、金牌厨师HiLin与HJGG
#include <cstdio>
using namespace std;
const int MaxN = 2e3 + 5;
long long a[MaxN][MaxN] , k ;
int n ;
void inti(){
for(int i = 1 ; i <= n ; ++i){
for(int j = 1; j <= n ; ++j){
a[i][j] += a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];
}
}
}
bool check(int x){
long long res ;
for(int i = x ; i <= n ; ++i){
for(int j = x ; j <= n ; ++j){
res = a[i][j] - a[i - x][j] - a[i][j - x] + a[i - x][j - x];
if(res >= k)return true;
}
}
return false;
}
int main(){
scanf("%d %lld",&n,&k);
for(int i = 1; i <= n ; ++i){
for(int j = 1;j <= n ; ++j)scanf("%lld",&a[i][j]);
}
inti();
int l = 1 , r = n , ans = 0;
while(l <= r){
int mid = l + r >> 1;
if(check(mid)){
ans = mid ;
r = mid - 1;
}
else l = mid + 1;
}
if(!ans)puts("I'm a Gold Chef!");
else printf("%d\n",ans);
return 0 ;
}
M、简单快乐棋
本题主要考察STL容器的使用以及代码能力。
我们需要做的就是记录空位置、各个英雄的位置、各个英雄的星级,分别使用优先队列、map、set(比较推荐set,因为是自动排序)或者vector就可以实现在使用妮蔻之助前的状态变化了。
由于本题为了简化,我们限定优先对更容易升星的英雄使用道具,并且妮蔻之助的数量较少,所以只需要按顺序依次对用1个、2个、3个妮蔻能升星的英雄进行操作即可。
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define pb push_back
typedef long long LL;
using namespace std;
const int maxn = 1E5 + 5;
const int inf = (1 << 30);
int n, m, k;
string id, ans[maxn];
priority_queue<int, vector<int>, greater<int> > rem;
map<string, int> cnt;
map<string, vector<int> > pos;
int now;
set<string> three, two, one, all;
set<string>::iterator it;
void up(int to, int ned){
if(to == 3){
it = two.begin();
while(k >= ned && it != two.end()){
if(cnt[*it + "**"] == 2 && 3 - cnt[*it] == ned){
for(int i = 0; i < pos[*it + "**"].size(); ++i){
ans[pos[*it + "**"][i]] = '#';
rem.push(pos[*it + "**"][i]);
}
for(int i = 0; i < pos[*it].size(); ++i){
ans[pos[*it][i]] = '#';
rem.push(pos[*it][i]);
}
pos[*it + "**"].clear();
pos[*it].clear();
now = rem.top(); rem.pop();
three.insert(*it);
ans[now] = *it + "***";
k -= ned;
}
it++;
}
}
else if(to == 2){
it = one.begin();
while(k >= ned && it != one.end()){
if(3 - cnt[*it] == ned){
for(int i = 0; i < pos[*it].size(); ++i){
ans[pos[*it][i]] = '#';
rem.push(pos[*it][i]);
}
pos[*it].clear();
now = rem.top(); rem.pop();
ans[now] = *it + "**";
k -= ned;
}
it++;
}
}
}
int main(){
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; ++i){
cin >> id;
ans[i] = id;
if(id[0] == '#') rem.push(i);
else{
cnt[id]++;
one.insert(id);
all.insert(id);
pos[id].pb(i);
}
}
while(m--){
cin >> id;
if(three.count(id)) continue;
if(cnt[id] == 2){
ans[pos[id][0]] = '#';
ans[pos[id][1]] = '#';
rem.push(pos[id][0]);
rem.push(pos[id][1]);
one.erase(id);
cnt[id] -= 2;
pos[id].clear();
id += "**";
cnt[id]++;
if(cnt[id] == 3){
cnt[id] -= 3;
ans[pos[id][0]] = '#';
ans[pos[id][1]] = '#';
rem.push(pos[id][0]);
rem.push(pos[id][1]);
now = rem.top(); rem.pop();
pos[id].clear();
two.erase(id);
id += '*';
ans[now] = id;
three.insert(id.substr(0, id.length() - 3));
}else{
now = rem.top(); rem.pop();
ans[now] = id;
pos[id].pb(now);
two.insert(id.substr(0, id.length() - 2));
}
}else{
if(rem.empty()) continue;
now = rem.top(); rem.pop();
one.insert(id);
all.insert(id);
cnt[id]++;
ans[now] = id;
pos[id].pb(now);
}
}
up(3, 1);
up(3, 2);
up(3, 3);
up(2, 1);
up(2, 2);
up(2, 3);
it = all.begin();
while(k > 0 && it != all.end()){
if(rem.empty()) break;
if(three.count(*it)){
it++;
continue;
}
now = rem.top(); rem.pop();
ans[now] = *it;
it++;
--k;
}
cout << three.size() << endl;
for(it = three.begin(); it != three.end(); it++){
cout << *it << endl;
}
for(int i = 1; i <= n; ++i){
cout << ans[i] << ' ';
}
cout << endl;
return 0;
}

全部评论
(1) 回帖