三个人玩石头剪刀布平局,其中两个出的分别是,求另一个人出的。
(分别表示石头,剪刀,布)
用整数格式输出答案。
输出 | ||
---|---|---|
石头剪刀布这个游戏三人平局只有两种情况(设为第三个人出的):
所以,我们得出如下递推式:
#include <cstdio>
using namespace std;
int main()
{
int x, y;
scanf("%d%d", &x, &y);
printf("%d\n", x == y? x: 3 - x - y);
return 0;
}
有棵树,第棵树上有颗果实。
一个人会从第棵树摘下颗果实。他一共会得到多少果实?
输出答案。
3
6 17 28
25
他会从三棵树上分别摘下颗果实,总共颗。
4
8 9 10 11
1
他只会从最后一棵树上得到一颗果实。
我们直接按题意模拟即可。
#include <cstdio>
using namespace std;
int main()
{
int n, ans = 0;
scanf("%d", &n);
while(n--)
{
int a;
scanf("%d", &a);
if(a > 10) ans += a - 10;
}
printf("%d\n", ans);
return 0;
}
一个国家有编号为至的座城市和编号为至的条路。
第条路从城市到,且不能用它从城市到。
一个人想从起点城市开始旅行并走过若干条路(可以不走,即只游玩一个城市)并到达终点城市。
有多少种合法的起点和终点城市?如果,则和算作两种不同的方案。
互不相同。
输出答案。
3 3
1 2
2 3
3 2
7
有七种可行的旅游方案:、、、、、、。
3 0
3
有三种可行的旅游方案:、、。
我们可以把这个国家看成一个简单有向无权图,并把每个节点作为起点跑一遍,计算总共能到达的结点数即可。
总时间复杂度为。
注意:每次之前一定要将数组清零!
#include <cstdio>
#include <vector>
#define maxn 2005
using namespace std;
vector<int> G[maxn];
bool vis[maxn];
int ans;
void dfs(int v)
{
if(vis[v]) return;
vis[v] = true, ans ++;
for(int u: G[v])
dfs(u);
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
while(m--)
{
int x, y;
scanf("%d%d", &x, &y);
G[--x].push_back(--y);
}
ans = 0;
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
vis[j] = false;
dfs(i);
}
printf("%d\n", ans);
return 0;
}
两个人要洗个碗,其中任意一个人洗第个碗需要分钟。一个人不能同时洗多个碗。
两个人一起洗碗,洗完所有碗至少需要多少分钟?
输出答案。
5
8 3 7 2 5
13
我们可以让两个人分别洗如下的碗:
总耗时为分钟。
2
1000 1
1000
9
3 14 15 9 26 5 35 89 79
138
这是一道经典01背包题。
题目可以直接描述为:给定序列,将其分成两个子序列和(不要求连续),求最小的。
这时,我们发现要使最小,由于,所以必须也达到最小。
我们可以将分成两半,其中一半为。这时,我们可以用dp背包解决此题:从中选出一个子序列,使得,这样答案就为。
#include <cstdio>
#define maxn 105
#define maxv 100005
using namespace std;
int dp[maxv], w[maxn];
inline void setmax(int& x, int y)
{
if(y > x) x = y;
}
int main()
{
int n, v = 0;
scanf("%d", &n);
for(int i=0; i<n; i++)
{
scanf("%d", w + i);
v += w[i];
}
int t = v;
v >>= 1;
for(int i=0; i<n; i++)
for(int j=v; j>=w[i]; j--)
setmax(dp[j], dp[j - w[i]] + w[i]);
printf("%d\n", t - dp[v]);
return 0;
}
一个国家有座城市和条路。城市的编号是至,路的编号则为至。第条路双向连接着城市和。
在这个国家中,初始时间为。如果你在时间点通过公路,所需时间为。
一个人想从城市到达城市。他在每个城市可以停留任意自然数的时间。
求这个人最早到达城市的时间。如果无法到达城市,输出-1
。
输出答案。
2 1
1 2 2 3
4
我们可以先在城市停留至时间。然后,我们出发,最终到达时间。
2 3
1 2 2 3
1 2 2 1
1 1 1 1
3
两个城市之间可能有多条路,一个城市也可能有到自己的路。
4 2
1 2 3 4
3 4 5 6
-1
城市到城市可能没有路径。
我们可以把输入当成一幅无向图。其实,从一个城市到它自己的路根本没有用,所以我们直接忽略不计。
如果目前时间为且我们要从城市到,我们可以证明,最好的整数出发时间应该是(表示四舍五入)。
如果,我们应该等到时间再出发;否则,我们直接出发。
这时,我们可以使用Dijkstra最短路算法(使用优先队列优化),这样总时间复杂度就为。
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#include <tuple>
#define maxn 100005
#define INF 9223372036854775807LL
using namespace std;
using Road = tuple<int, int, int>;
using LL = long long;
using pli = pair<LL, int>;
vector<Road> G[maxn];
LL dist[maxn];
int main()
{
int n, m;
scanf("%d%d", &n, &m);
while(m--)
{
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
if(--a == --b) continue;
G[a].emplace_back(b, c, d);
G[b].emplace_back(a, c, d);
}
dist[0] = 0LL;
for(int i=1; i<n; i++) dist[i] = INF;
priority_queue<pli, vector<pli>, greater<pli>> q;
q.emplace(0LL, 0);
while(!q.empty())
{
auto [t, u] = q.top(); q.pop();
if(dist[u] != t) continue;
for(auto [v, c, d]: G[u])
{
LL t2 = sqrt((long double) d) - 0.5;
if(t2 < t) t2 = t;
t2 += LL(c) + LL(d) / (t2 + 1LL);
if(t2 < dist[v])
q.emplace(dist[v] = t2, v);
}
}
if(dist[n - 1] == INF) puts("-1");
else printf("%lld\n", dist[n - 1]);
return 0;
}