某学校植树节开展植树活动,已知树苗有m株,参加植树的同学有n人(且m>n),请问每位同学平均可以植树几株?还有几株剩余?
输入两个整数m和n,分别表示树苗的数量和学生的人数(m>n)。
输出两个整数,分别表示每位同学平均植树的数量及剩余的树苗数量。
163 32
5 3
#include
using namespace std;
int m, n;
signed main() {
cin >> m >> n;
cout << m / n << ' ' << m % n;
return 0;
}
本题要求编写程序,根据输入的三角形的三条边a、b、c,计算并输出面积和周长。注意:在一个三角形中, 任意两边之和大于第三边。三角形面积计算公式:
a r e a = s ( s − a ) ( s − b ) ( s − c ) area=s(s−a)(s−b)(s−c) area=s(s−a)(s−b)(s−c)
其中
s = ( a + b + c ) / 2 s=(a+b+c)/2 s=(a+b+c)/2
输入为3个正整数,分别代表三角形的3条边a、b、c。
如果输入的边能构成一个三角形,则在一行内,按照
area = 面积; perimeter = 周长
的格式输出,保留两位小数。否则,输出
These sides do not correspond to a valid triangle
5 5 3
area = 7.15; perimeter = 13.00
1 4 1
These sides do not correspond to a valid triangle
#include
using namespace std;
int a, b, c;
signed main() {
cin >> a >> b >> c;
double s = (a + b + c) / 2.0;
double area = sqrt(s * (s - a) * (s - b) * (s - c));
double p = a + b + c;
if (a + b > c && b + c > a && a + c > b)
printf("area = %.2f; perimeter = %.2f\n", area, p);
else
printf("These sides do not correspond to a valid triangle");
return 0;
}
根据某城市普通出租车收费标准编写程序进行车费计算。具体标准如下:
起步里程为3公里,起步费10元;
超起步里程部分且10公里内,每公里2元;
超过10公里以上的部分加收50%的回空补贴费,即每公里3元。
如果输入值为负数,则输出“Input error!"
在一行中给出输入行驶里程(单位为公里)
在一行中输出乘客应支付的车费(单位为元),结果四舍五入,保留到元。
在这里给出一组输入。例如:
-1
在这里给出相应的输出。例如:
Input error!
在这里给出一组输入。例如:
2.6
在这里给出相应的输出。例如:
10
在这里给出一组输入。例如:
3
在这里给出相应的输出。例如:
10
在这里给出一组输入。例如:
9.8
在这里给出相应的输出。例如:
24
在这里给出一组输入。例如:
10
在这里给出相应的输出。例如:
24
在这里给出一组输入。例如:
12.2
在这里给出相应的输出。例如:
31
%.0f
即可#include
using namespace std;
signed main() {
double x;
cin >> x;
if (x < 0) {
puts("Input error!");
}
else if (x <= 3) {
cout << 10;
}
else if (x <= 10) {
printf("%.0f\n", 10.0 + (x - 3) * 2.0);
}
else if (x > 10) {
printf("%.0f\n", 10.0 + 7 * 2.0 + (x - 10) * 3.0);
}
return 0;
}
用户从键盘输入一个整数,程序将判断这个数是几位数并输出其位数,并判断这个数是否是回文数,是则输出Y,否则输出N。回文数是指将该数含有的数字逆序排列后得到的数和原数相同,例如12121、3223都是回文数。
整数
几位数
是否是回文数
在这里给出一组输入。例如:
12121
在这里给出相应的输出。例如:
5
Y
#include
using namespace std;
bool check(string s) {
for (int i = 0; i < s.size() / 2; i++) {
if (s[i] != s[s.size() - i - 1])
return false;
}
return true;
}
// 直接反转判断
bool check1(string s) {
string str = s;
reverse(s.begin(), s.end());
return str == s;
}
signed main() {
string str;
cin >> str;
cout << str.size() << endl;
cout << (check(str) ? "Y" : "N");
return 0;
}
公鸡每只5元,母鸡每只3元,小鸡1元3只,而且鸡必须整只买。100元钱买100只鸡(每一种鸡都要有),公鸡、母鸡、小鸡各多少只?请编写程序给出各种购买方案。
输入为一个正整数n,表示要求输出前n种可能的方案。方案的顺序,是按照公鸡只数从少到多排列的。
显示前n种方案中公鸡、母鸡、小鸡各多少只。每行显示一种方案,数字之间空一格,最后一个数字后没有空格。
注意:如果全部方案不到n种,就顺序输出全部可能的方案。
在这里给出一组输入。例如:
5
在这里给出相应的输出。例如:
4 18 78
8 11 81
12 4 84
#include
using namespace std;
int n, cnt;
signed main() {
cin >> n;
for (int i = 1; i <= 20; i++) { //5
for (int j = 1; j <= 33; j++) { // 3
for (int k = 1; k <= 33; k++) {
if (i * 5 + j * 3 + k == 100 && i + j + k * 3 == 100 && cnt < n)
{
cout << i << ' ' << j << ' ' << k * 3 << endl;
cnt ++;
}
}
}
}
return 0;
}
国王以金币支付给他忠诚的骑士。在他服役的第一天,骑士会得到一枚金币。在接下来的每两天(服务的第二和第三天),骑士会收到两枚金币。在在接下来的三天里(第四、第五和第六天),骑士每一天都会得到三枚金币。在接下来的4天里(第七、第八、第九和第十天),每一天骑士会得到4枚金币。这种支付模式将无限期地持续下去:在每个N在接下来的连续N+1天里,骑士将获得N+1个金币,其中N是任意正整数。请你编写程序将确定在任何给定的天数内支付给骑士的金币总数(从第一天开始)。
输入的每一行(最后一行除外)都包含问题的一个测试用例的数据,由精确的1个整数(取值范围1…10000),表示天数。输入的结束以一行作为信号包含数字0。
每个测试用例只有一行输出。先输出相应的一行输入的天数,后面跟着一个空格和支付给骑士的金币总数在给定的天数内,从第一天开始。
10
6
7
11
15
16
100
10000
1000
21
22
0
10 30
6 14
7 18
11 35
15 55
16 61
100 945
10000 942820
1000 29820
21 91
22 98
题意要求我们构造一个类似于
1 , 2 , 2 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , 5 , 5 , 5 , 5 , 5...... 1, 2, 2, 3, 3,3, 4, 4, 4, 4, 5, 5, 5, 5, 5 ...... 1,2,2,3,3,3,4,4,4,4,5,5,5,5,5......
这样的数列,我们按题意预处理构造即可
同时注意最大天数为1e5 大概处理500个这样的数即可
#include
#define pb push_back
using namespace std;
int n, x;
signed main() {
vector v; v.pb(0);
for (int i = 1; i <= 500; i++) {
for (int j = 1; j <= i; j++)
v.pb(i);
}
while (cin >> x, x) {
cout << x << ' ';
int res = 0;
for (int i = 1; i <= x; i ++) res += v[i];
cout << res << endl;
}
return 0;
}
给定一个 n×m 的整数矩阵,求矩阵中的所有鞍点。
鞍点,即该位置上的元素在该行上最大,在该列上最小。
有可能有多个鞍点,也可能没有鞍点。
第一行包含两个整数 n,m(1≤n,m<10)。
接下来 n 行,每行包含 m 个整数x(1≤x<10)。
输出所有鞍点的坐标和值。
输出优先级,整体从上到下,同行从左到右。
如果不存在鞍点,则输出 NO。
3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 4 4
2 4 4
3 4 4
#include
using namespace std;
const int N = 10 + 7, inf = 0x3f3f3f3f;
int n, m;
int g[N][N];
signed main() {
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> g[i][j];
bool f = false;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
int maxv = -1, minv = inf;
for (int k = 1; k <= m; k++) {
if (maxv <= g[i][k])
maxv = g[i][k];
}
for (int k = 1; k <= n; k++) {
if (minv >= g[k][j])
minv = g[k][j];
}
if (maxv == minv)
{
f = true;
cout << i << ' ' << j << ' ' << g[i][j] << endl;
}
}
}
if (!f) puts("NO");
return 0;
}
您刚刚从毕节搬到了一个大城市。这里的人说的是一门不可理解的外语。幸运的是,您有一本字典可以帮助您理解它们。
输入最多包含100,000个字典条目,后跟一个空白行,然后是最多100,000个单词的消息。每个字典条目都是一行,包含英文单词,后跟一个空格和一个外语单词。在词典中,没有外来词出现多次。该消息是外语单词序列,每行一个单词。输入中的每个单词都是最多10个小写字母的序列。
输出是将消息翻译成英语,每行一个单词。词典中没有的外来词应翻译为“ eh”。
dog ogday
cat atcay
pig igpay
froot ootfray
loops oopslay
atcay
ittenkay
oopslay
cat
eh
loops
getline
读入整行,再分割出单词stringstream
,它会忽略空格读入;也可以用find找空格再截取出来#include
using namespace std;
string str, a, b;
unordered_map st1, st2;
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
while (getline(cin, str) && str != "") {
//int k = str.find(' ');
//string a = str.substr(0, k), b = str.substr(k + 1);
stringstream ss(str);
ss >> a >> b;
st1[a] = b, st2[b] = a;
}
while (cin >> str) {
if (st1.count(str)) cout << st1[str] << endl;
else if (st2.count(str)) cout << st2[str] << endl;
else cout << "eh\n";
}
return 0;
}
一种自动包装机的结构如图 1 所示。首先机器中有 N 条轨道,放置了一些物品。轨道下面有一个筐。当某条轨道的按钮被按下时,活塞向左推动,将轨道尽头的一件物品推落筐中。当 0 号按钮被按下时,机械手将抓取筐顶部的一件物品,放到流水线上。图 2 显示了顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态。
图1 自动包装机的结构
图 2 顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态
一种特殊情况是,因为筐的容量是有限的,当筐已经满了,但仍然有某条轨道的按钮被按下时,系统应强制启动 0 号键,先从筐里抓出一件物品,再将对应轨道的物品推落。此外,如果轨道已经空了,再按对应的按钮不会发生任何事;同样的,如果筐是空的,按 0 号按钮也不会发生任何事。
现给定一系列按钮操作,请你依次列出流水线上的物品。
输入第一行给出 3 个正整数 N(≤100)、M(≤1000)和 Smax(≤100),分别为轨道的条数(于是轨道从 1 到 N 编号)、每条轨道初始放置的物品数量、以及筐的最大容量。随后 N 行,每行给出 M 个英文大写字母,表示每条轨道的初始物品摆放。
最后一行给出一系列数字,顺序对应被按下的按钮编号,直到 −1 标志输入结束,这个数字不要处理。数字间以空格分隔。题目保证至少会取出一件物品放在流水线上。
在一行中顺序输出流水线上的物品,不得有任何空格。
3 4 4
GPLT
PATA
OMSA
3 2 3 0 1 2 0 2 2 0 -1
MATA
vector
存各个队列,输入为了方便弹出尾部元素,反转了一下。也可以先直接通过front()
取出队头,再erase()
删除第一个元素。#include
using namespace std;
int x;
stack st;
vector v;
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n, m, k;
cin >> n >> m >> k;
v.resize(n + 1);
for (int i = 1; i <= n; i++) {
cin >> v[i];
//反转一下方便pop_back
reverse(v[i].begin(), v[i].end());
}
while (cin >> x && x != -1) {
if (x != 0 && !v[x].empty()) {
if (st.size() == k) {
cout << st.top();
st.pop();
st.push(v[x].back());
v[x].pop_back();
}
else {
st.push(v[x].back());
v[x].pop_back();
}
}
else if (x == 0) {
if (st.size()) {
cout << st.top();
st.pop();
}
}
}
return 0;
}
春节至,亲朋好友聚会忙,聚会之人有时会说到自己的生肖。对于给定的若干人的生肖,请统计各种生肖的人数,并按人数从多到小输出各种出现的生肖及其人数。若有多种生肖的人数相同,则按生肖英文单词(详见最后的提示)的字典序输出。
首先输入一个正整数T,表示测试数据的组数,然后是T组测试数据。每组测试先输入1个整数n(1<=n<=100)表示聚会人数,再输入n个字符串(长度不超过7且仅包含小写字母),每个字符串表示一个人的生肖。
对于每组测试,按描述要求输出结果,每种出现的生肖及其人数占一行,每行的两个数据之间以一个空格间隔。每两组测试数据之间留一个空行。
2
4
tiger
rabbit
dragon
rabbit
5
tiger
rabbit
dragon
rabbit
dragon
rabbit 2
dragon 1
tiger 1
dragon 2
rabbit 2
tiger 1
鼠、牛、虎、兔、龙、蛇、马、羊、猴、鸡、狗、猪等十二生肖相应的英文单词如下:
rat、ox、tiger、rabbit、dragon、snake、horse、goat、monkey、rooster、dog、pig
string
比较即可(因为string
类重载了运算符)cmp(
)函数 or 重载<
都可#include
using namespace std;
#define endl '\n'
#define pb push_back
const int N = 1000 + 7;
int n, t;
struct node {
string a;
int k;
bool operator<(const node &o) const {
if (k == o.k) return a < o.a;
return k > o.k;
}
};
signed main() {
cin >> t;
for (int i = 1; i <= t; i++) {
cin >> n;
unordered_map cnt;
while (n--) {
string str;
cin >> str;
cnt[str] ++;
}
vector ans;
for (auto [k, v] : cnt) ans.pb({k, v});
sort(ans.begin(), ans.end());
for (auto [a, b] : ans) cout << a << ' ' << b << endl;
if (i != t) cout << endl;
}
return 0;
}
Tabu市的警察局决定结束混乱,因此要采取行动根除城市中的几大帮派。目前的问题是,给出两个罪犯,他们是属于同一帮派么?城市里一共有多少个帮派?假设在Tabu市现有n名罪犯,编号为1到n,给出m条消息表示属于同一帮派的两个罪犯编号。请基于这些不完全的信息帮助警方计算出他们想要的信息。
输入第一行为三个正整数,n、m和q。n为罪犯数;m为给出的已知信息数量;q为查询数。接下来m行,每行2个正整数a和b,表示罪犯a和罪犯b属于同一帮派。接下来q行,每行2个正整数c和d,即查询罪犯c和d是否属于同一帮派。每行输入的整数以空格间隔,n、m、q均不超过1000。
输出为q+1行,前q行对应于输入的q个查询的结果,如果属于同一帮派,则输出“In the same gang.”,否则输出“In different gangs.”。最后一行为一个整数,表示帮派数目。
3 2 1
1 2
2 3
1 3
In the same gang.
1
#include
using namespace std;
const int N = 1e3 + 7;
int n, m, q, cnt;
int p[N];
int find(int x) {
if (x != p[x]) p[x] = find(p[x]);
return p[x];
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
cin >> n >> m >> q;
for (int i = 1; i <= n; i++) p[i] = i;
while (m --) {
int a, b;
cin >> a >> b;
int fa = find(a), fb = find(b);
if (fa != fb) p[fa] = fb;
}
while (q--) {
int a, b;
cin >> a >> b;
if (find(a) == find(b)) cout << "In the same gang.\n";
else cout << "In different gangs.\n";
}
int res = 0;
for (int i = 1; i <= n; i++)
if (p[i] == i)
res ++;
cout << res << endl;
return 0;
}
xt是我院19级专业第一,但他认为保研并不能展示他全部的实力,所以他在22年初试一结束就加入了23考研的队伍中,并且他为了填补我院近些年来无北大研究生的空白,毅然决然决定扛起19级的大旗,在学校百年华诞之际献上他最诚挚的礼物。
xt每天都游走在寝室,食堂和图书馆,三点一线,即便是在疫情局势蔓延的形势下,凌晨三点半刚做完核酸,他六点半还是照常起来卷。现在他太忙了,好像在提前准备复试了,想让你帮个小忙,xt会给出学校的地图(有向图),并且给出寝室,食堂和图书馆的编号(编号从0开始),希望你从该图中找出一个子图,要使得在这个子图中,寝室能够到达图书馆,食堂也能到达图书馆,同时希望在这个子图中的所有边的边权之和最小。如果你找不到任何一个子图符合要求的话(),输出“xt,我好没本领!”,因为你找不到并不代表xt找不到
子图的定义:
从原图中删去一些点或删去一些线或既删去一些点又删去一些线,剩下的部分(当然必须仍然是图)。允许两种极端情况:什么都不删;删去所有点和所有线。
第一行输入点的个数 n,3 <= n <= 105,边的个数 m,0 <= m <= 2∗105
第二行给出寝室的编号id1,食堂的编号id2,图书馆的编号id3,题目保证三个编号两两不同。
随后 m 行按照以下形式描述边,表示有一条有向边,起点是from,终点是to,权值是w
from to w
0 <= from, to <= n - 1,from != to,1 <= w <= 109
如果子图存在则输出最小边权和,如果不存在输出“xt,我好没本领!”
6 9
0 1 5
0 2 2
0 5 6
1 0 3
1 4 5
2 1 1
2 3 3
2 3 4
3 4 2
4 5 1
9
上图为输入的图。
蓝色边为最优子图之一。
注意,直接选择0 1 5
三点构成的子图也能得到最优解,但无法在满足所有限制的前提下,得到更优解。
3 2
0 1 2
0 1 1
2 1 1
xt,我好没本领!
上图为输入的图。
可以看到,不存在从节点 1 到节点 2 的路径,所以不存在任何子图满足所有限制。
这题出在L2有点不太合理的,当时没看明白,感觉复杂就跳过了,现在一看还是需要点思维的,看了别人写的题解才懂了点思路。
题意:给定一个有向图,要求出一张子图,使得两个起点都能到达终点,且子图内的边权之和最小。
首先从边权之和最小我们自然而然地联系到最短路,从两个起点分别跑最短路,即起点1到终点,起点2到终点,但最终的答案可能并不是两条最短路简单相加(这种解法亲测13分),因为中间可能会有重复部分,而我们要使得答案最小,就要使得重合的部分尽量的多,所以说直接跑两遍最短路再减去重复部分可能得不到最优解,因为二者的目的不同。
所以最终的子图应该是一个Y形,即两个起点到达某一个中间点,再一起从中间点到终点。
参考详解:xt的考研路
dijkstra
,并反向建图从终点跑一遍dijkstra
,分别开dist
数组记录最短路径vector
or 链式前向星
)用堆优化djikstra
算法#include
#define int long long
#define x first
#define y second
using namespace std;
typedef pair PII;
const int N = 1e5 + 7, inf = 0x3f3f3f3f;
int n, m, a, b, c, id1, id2, id3;
bool st[N];
vector dijkstra(vector > &g, int u) {
vector dist(g.size());
fill(dist.begin(), dist.end(), inf / 3);
memset(st, false, sizeof st);
dist[u] = 0;
priority_queue, greater<>> heap;
heap.emplace(0, u);
while (!heap.empty()) {
auto t = heap.top();
heap.pop();
int ver = t.y, distance = t.x;
if (st[ver]) continue;
st[ver] = true;
for (auto v: g[ver]) {
int j = v.x, w = v.y;
if (distance + w < dist[j]) {
dist[j] = distance + w;
heap.emplace(dist[j], j);
}
}
}
return dist;
}
signed main() {
cin.tie(nullptr)->ios::sync_with_stdio(false);
cin >> n >> m;
cin >> id1 >> id2 >> id3;
vector > g(n), rg(n);
while (m--) {
cin >> a >> b >> c;
g[a].emplace_back(b, c);
rg[b].emplace_back(a, c);
}
auto dist1 = dijkstra(g, id1);
auto dist2 = dijkstra(g, id2);
auto dist3 = dijkstra(rg, id3);
int res = inf;
for (int i = 0; i < n; i++) {
res = min(res, dist1[i] + dist2[i] + dist3[i]);
}
if (res < inf / 3) {
cout << res << endl;
}
else {
cout << "xt,我好没本领!" << endl;
}
return 0;
}
第一行四个用空格隔开的正整数表示 N,M,X,Y,分别表示 N 行 M 列的地图,小星星起
始位置第 X 行,第 Y 列。
接下来 N 行 M 列用来描述地图上每个单元格,‘G’表示僵尸,‘#’表示墙体,只有‘.’
表示的单元格才是小星星能够正常行走,能够放置炸弹的单元格。(数据保证四面都是墙体,
也就是第 1 行、第 N 行、第 1 列、第 M 列肯定都是墙体)。
一个整数,最多能炸掉的僵尸数量。
13 13 4 2
#############
###..GG#GGG.#
###.#G#G#G#G#
#.......#..G#
#G#.###.#G#G#
#GG.GGG.#.GG#
#G#.#G#.#.#.#
##G...G.....#
#G#.#G###.#G#
#...G#GGG.GG#
#G#.#G#G#.#G#
#GG.GGG#G.GG#
#############
10
【数据范围】
30%的数据,保证 N,M<14,并且小星星一定能够抵达最佳炸弹放置点
40%的数据,保证 N,M<14
70%的数据,保证 N,M<101
100%的数据,保证 N,M<2001
100%的数据,保证 X
DFS or BFS
搜索出所有能走到的点,再更新最大炸到僵尸数量即可DFS
写法和BFS
写法都在下面#include
#define x first
#define y second
using namespace std;
typedef pair PII;
const int N = 2e3 + 7;
int n, m, x, y, res;
char g[N][N];
bool st[N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int count(int x, int y) {
int cnt = 0;
//判断左右
for (int j = y - 1; j >= 1; j--) {
if (g[x][j] == '#') break;
if (g[x][j] == 'G') cnt ++;
}
for (int j = y + 1; j <= m; j++) {
if (g[x][j] == '#') break;
if (g[x][j] == 'G') cnt ++;
}
//判断上下
for (int i = x + 1; i <= n; i++) {
if (g[i][y] == '#') break;
if (g[i][y] == 'G') cnt ++;
}
for (int i = x - 1; i >= 1; i--) {
if (g[i][y] == '#') break;
if (g[i][y] == 'G') cnt ++;
}
return cnt;
}
void bfs(int x, int y) {
queue q;
q.emplace(x, y);
st[x][y] = true;
res = count(x, y);
while (!q.empty()) {
auto t = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int a = t.x + dx[i], b = t.y+ dy[i];
if (a < 1 || a > n || b < 1 || b > m ) continue;
if (g[a][b] == '#' || g[a][b] == 'G' || st[a][b]) continue;
if (g[a][b] == '.')
{
int cnt = count(a, b);
res = max(res, cnt);
st[a][b] = true;
q.emplace(a, b);
}
}
}
}
void dfs(int x, int y) {
if (g[x][y] == '.')
res = max(res, count(x, y));
for (int i = 0; i < 4; i++) {
int a = x + dx[i], b = y + dy[i];
if (a >= 1 && a <= n && b >= 1 && b <= m && g[a][b] == '.' && !st[a][b]) {
st[a][b] = true;
dfs(a, b);
}
}
}
signed main() {
cin >> n >> m >> x >> y;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> g[i][j];
//bfs(x, y);
dfs(x, y);
cout << res << endl;
return 0;
}
/*
如何处理同一个格子不能被重复选择
只有在i1 + j1 = i2 + j2 时候两条路径的格子才可能重合
由摘花生的问题可以推出三维状态转移方程 :
f[i1, k-i1, i2, k -i2] - > f[k, i1, i2]
f[k, i, j] 表示所有从(1,1)分别走到(i1, k - i1), (i2, k - i2)的路径的最大值
k表示两条路线当前走到的格子的横纵坐标之和 (k = i1 + j1 = i2 + j2)
难点:格子仅能取一次. 两个小朋友在同一个格子必有i1==i2,j1==j2,
而后边状态限制同时走,所以当i1==i2时便走到同一格.
判断(i1,j1),(i2,j2)是否是同一个格子,若是则仅需要加上一个权重,反之两个都需要
*/
#pragma GCC optimize(2)
#include
using namespace std;
const int N = 15;
int n;
int g[N][N];
int f[2 * N][N][N];
signed main() {
cin >> n;
int a, b, w;
while (cin >> a >> b >> w, a || b || w) g[a][b] = w;
for (int k = 2; k <= n + n; k++) {
for (int i1 = 1; i1 <= n; i1++) {
for (int i2 = 1; i2 <= n; i2++) {
int j1 = k - i1, j2 = k - i2;
if (j1 >= 1 && j1 <= n && j2 >= 1 && j2 <= n) { //防止越界
int t = g[i1][j1];
if (i1 != i2) t += g[i2][j2]; //不重合则两条路径都需要加权重
int &x = f[k][i1][i2];
x = max(x, f[k - 1][i1 - 1][i2 - 1] + t);
x = max(x, f[k - 1][i1 - 1][i2] + t);
x = max(x, f[k - 1][i1][i2 - 1] + t);
x = max(x, f[k - 1][i1][i2] + t);
}
}
}
}
cout << f[n + n][n][n];
return 0;
}
暴搜解法
状压DP解法
题目出处