解题报告: Codeforces Round #536 (Div.2)
能力不足,比赛时间结束时只解出A,B,C,D题。以下为这些题个人的解题思路及代码,不喜勿喷。
Problem A Lunar New Year and Cross Counting
题意
给你一个由字符组成的矩阵。
当位置(i, j),(i - 1, j - 1), (i - 1, j + 1), (i + 1, j - 1), (i + 1, j + 1)的字符均为’X’时组成一个“大叉”。
编写一个程序该矩阵中一共有多少个“大叉”。
解法
对于每一个不在边缘上的点,根据题意检查其是否符合标准即可。
以下是代码
//Codeforces Round #536 (Div.2)
//Problem A
//EnRonG
#include <stdio.h>
#include <string.h>
int n_Ans;
int n_Size;
char s_Matrix[501][501];
int main()
{
scanf ("%d", &n_Size);
for (int i = 0; i < n_Size; i++)
{
scanf ("%s", s_Matrix[i]);
}
for (int i = 1; i < n_Size - 1; i++)
{
for (int j = 1; j < n_Size - 1; j++)
{
if (s_Matrix[i][j] == 'X' && s_Matrix[i - 1][j - 1] == 'X' &&
s_Matrix[i + 1][j - 1] == 'X' && s_Matrix[i - 1][j + 1] == 'X' &&
s_Matrix[i + 1][j + 1] == 'X')
{
n_Ans++;
}
}
}
printf ("%d\n", n_Ans);
return 0;
}
Problem B Lunar New Year and Food Ordering
题意
一个餐厅,售卖N种菜品,共有M个顾客。
每一种菜都有制作成本以及初始数量。
现这M个顾客按顺序进行点餐,每个顾客都会要求点某个菜并给出需要多少份这个菜。上菜规则有如下三条:
- 如果顾客点的这个菜的剩余数量多于顾客所需要的数量,则直接给顾客这么多菜,收入为该菜品的制作成本 x 顾客需要的数量
- 如果顾客点的这个菜的剩余数量少于顾客所需要的数量,将该菜品剩下的所有菜都给该顾客。并制作若干制作成本最低的菜品给该顾客,来补齐顾客需要的数量。收入即做好所有菜的成本。
- 如果顾客点的菜数量太多,餐厅无法提供足够的菜,收入为0,并且顾客提走剩下的所有的菜。
现给出菜品数量、顾客数量、菜品制作成本、菜品初始剩余量、以及顾客的需求。
要求对于每个顾客的请求输出餐厅的收入。
解法
对于输入的菜品,对其按价格进行排序。
然后根据题意模拟过程即可。
//Codeforces Round #536 (Div.2)
//Problem B
//EnRonG
#include <stdio.h>
#include <map>
#define SIZE 100010
using namespace std;
map <long long, long long> m_Chart;
long long n_Amount;
long long n_DishID;
long long n_TrueID;
long long n_Find;
long long n_TotCust;
long long n_TotKind;
long long n_TotRemain;
long long n_NewID[SIZE];
long long n_Cost[SIZE];
long long n_RemainCnt[SIZE];
long long n_Fee;
void v_Swap(long long &n_Num1, long long & n_Num2)
{
long long n_Temp = n_Num1;
n_Num1 = n_Num2;
n_Num2 = n_Temp;
}
void v_Sort(long long n_Left, long long n_Right)
{
if (n_Left > n_Right)
{
return;
}
long long n_Left1 = n_Left;
long long n_Right1 = n_Right;
long long n_Temp = n_Cost[n_Left];
while (n_Left1 != n_Right1)
{
while (n_Cost[n_Right1] >= n_Temp && n_Left1 < n_Right1)
{
n_Right1--;
}
while (n_Cost[n_Left1] <= n_Temp && n_Left1 < n_Right1)
{
n_Left1++;
}
if (n_Left1 < n_Right1)
{
v_Swap(n_Cost[n_Left1], n_Cost[n_Right1]);
v_Swap(n_RemainCnt[n_Left1], n_RemainCnt[n_Right1]);
v_Swap(n_NewID[n_Left1], n_NewID[n_Right1]);
}
}
v_Swap(n_Cost[n_Left], n_Cost[n_Left1]);
v_Swap(n_RemainCnt[n_Left], n_RemainCnt[n_Left1]);
v_Swap(n_NewID[n_Left], n_NewID[n_Left1]);
v_Sort(n_Left, n_Left1 - 1);
v_Sort(n_Left1 + 1, n_Right);
}
int main()
{
scanf ("%I64d %I64d", &n_TotKind, &n_TotCust);
n_Find = 1;
for (int i = 1; i <= n_TotKind; i++)
{
scanf ("%I64d", &n_RemainCnt[i]);
n_TotRemain += n_RemainCnt[i];
n_NewID[i] = i;
}
for (int i = 1; i <= n_TotKind; i++)
{
scanf ("%I64d", &n_Cost[i]);
}
v_Sort(1, n_TotKind);
for (int i = 1; i <= n_TotKind; i++)
{
m_Chart.insert(pair<long long, long long>(n_NewID[i], i));
}
for (int i = 1; i <= n_TotCust; i++)
{
scanf ("%I64d %I64d", &n_DishID, &n_Amount);
if (n_TotRemain < n_Amount)
{
n_TotRemain = 0;
printf ("0\n");
continue;
}
n_TrueID = m_Chart[n_DishID];
if (n_RemainCnt[n_TrueID] >= n_Amount)
{
n_TotRemain -= n_Amount;
n_RemainCnt[n_TrueID] -= n_Amount;
n_Fee = n_Amount * n_Cost[n_TrueID];
}
else
{
n_Fee = n_RemainCnt[n_TrueID] * n_Cost[n_TrueID];
n_Amount -= n_RemainCnt[n_TrueID];
n_TotRemain -= n_RemainCnt[n_TrueID];
n_RemainCnt[n_TrueID] = 0;
while (n_Amount && n_Find <= n_TotKind)
{
while (!n_RemainCnt[n_Find] && n_Find <= n_TotKind)
{
n_Find++;
}
if (n_Find > n_TotKind)
{
break;
}
if (n_RemainCnt[n_Find] >= n_Amount)
{
n_RemainCnt[n_Find] -= n_Amount;
n_TotRemain -= n_Amount;
n_Fee += n_Amount * n_Cost[n_Find];
n_Amount = 0;
}
else
{
n_Fee += n_RemainCnt[n_Find] * n_Cost[n_Find];
n_Amount -= n_RemainCnt[n_Find];
n_TotRemain -= n_RemainCnt[n_Find];
n_RemainCnt[n_Find] = 0;
}
}
}
printf ("%I64d\n", n_Fee);
}
return 0;
}
反思
这份代码仍有待优化的地方,如果将每一个菜品的属性都放在一个结构体中,并重定向运算符<,利用stl库中的sort()函数可以提升该程序的运行效率,并简化代码。
Problem C Lunar New Year and Number Division
题意
给出N个数(保证N是偶数),将其分为M组。
求这M组数的和的平方的最小值。
解法
对于输入的这串数进行排序,每次取两端的数组成一组即可得最小值。
//Codeforces Round #536 (Div.2)
//Problem C
//EnRonG
#include <stdio.h>
#include <algorithm>
#define SIZE 300001
using namespace std;
long long n_TotNum;
long long n_Data[SIZE];
long long n_Sum;
int main()
{
scanf ("%I64d", &n_TotNum);
for (int i = 1; i <= n_TotNum; i++)
{
scanf ("%I64d", &n_Data[i]);
}
sort(n_Data + 1, n_Data + n_TotNum + 1);
for (int i = 1, j = n_TotNum; i < j; i++, j--)
{
n_Sum += (n_Data[i] + n_Data[j]) * (n_Data[i] + n_Data[j]);
}
printf ("%I64d\n", n_Sum);
return 0;
}
Problem D Lunar New Year and a Wander
题意
N个点、M条边。
保证连通成一张图。
求以最小字典序遍历这张图的方案。
解法
从ID为1的点开始遍历。
每遍历到1个点就将其能达到的点加入set中,然后再选set中最小的点继续进行遍历即可。
//Codeforces Round #536 (Div.2)
//Problem D
//EnRonG
#include <stdio.h>
#include <string.h>
#include <set>
#define SIZE 100001
using namespace std;
struct Edge
{
int n_ToPoint;
int n_NextEdgeID;
}e_Edge[SIZE << 2];
int n_From;
int n_HandlePt;
int n_To;
int n_TotEdgeB; //Counts Edges Already Built
int n_TotEdge;
int n_TotPoint;
int n_Book[SIZE];
int n_FirstEdge[SIZE];
int n_InSet[SIZE];
set <int> s_Points;
void v_BuildEdge(int n_From, int n_To)
{
n_TotEdgeB++;
e_Edge[n_TotEdgeB].n_ToPoint = n_To;
e_Edge[n_TotEdgeB].n_NextEdgeID = n_FirstEdge[n_From];
n_FirstEdge[n_From] = n_TotEdgeB;
n_TotEdgeB++;
e_Edge[n_TotEdgeB].n_ToPoint = n_From;
e_Edge[n_TotEdgeB].n_NextEdgeID = n_FirstEdge[n_To];
n_FirstEdge[n_To] = n_TotEdgeB;
}
void v_GetAns(int n_CurPointID)
{
printf ("%d ", n_CurPointID);
if (n_CurPointID != 1)
{
s_Points.erase(n_CurPointID);
}
for (int i = n_FirstEdge[n_CurPointID]; i != 0;
i = e_Edge[i].n_NextEdgeID)
{
n_HandlePt = e_Edge[i].n_ToPoint;
if (n_Book[n_HandlePt])
{
continue;
}
if (!n_InSet[n_HandlePt])
{
s_Points.insert(n_HandlePt);
n_InSet[n_HandlePt] = 1;
n_Book[n_HandlePt] = 1;
}
}
set<int>::iterator s_ITE;
if (s_Points.size())
{
s_ITE = s_Points.begin();
v_GetAns(*s_ITE);
}
}
int main()
{
scanf ("%d %d", &n_TotPoint, &n_TotEdge);
for (int i = 1; i <= n_TotEdge; i++)
{
scanf ("%d %d", &n_From, &n_To);
v_BuildEdge(n_From, n_To);
}
n_InSet[1] = 1;
n_Book[1] = 1;
v_GetAns(1);
set<int>::iterator s_ITE2;
if (s_Points.size())
{
for (s_ITE2 = s_Points.begin(); s_ITE2 != s_Points.end();
s_ITE2++)
printf ("%d ", *s_ITE2);
}
printf ("\n");
return 0;
}