版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27008079/article/details/53979953
Codeforces Good Bye 2016部分题解
今年的最后一场cf,打的并不好,感觉自己元旦期间好松懈。
题目链接
A. New Year and Hurry
题意:
现在20:00,Limak需要在24:00点前赶去派对,此时有n个问题,第i个问题花费时间5*i 分钟,从家到派队需要k分钟,问最多解决几个问题
思路:
纯模拟。
#include<iostream>
using namespace std;
int main()
{
int n, k;
int i = 0, j;
cin >> n >> k;
int s = k;
if(s <= 240)
for(i=1; i<=n; i++)
{
s += i * 5;
if(s > 240){
break;
}
}
cout << i - 1 << endl;
return 0;
}
B. New Year and North Pole
题意:
假定地球是标准的球体,从北极点到南极点长度40000km,赤道长度40000km,Limak目前在北极点,有以下规则:1.当Limak处于或行走过程中处于南极点时,他只能向北走。2.当Limak处于或行走过程中处于北极点时,他只能向南走。3.Limak最后要回到北极点。给出n个行走步骤,问是否合法。
思路:
思维题,行走中向东和向西走不用管,只用管南北方向的行走,判断处于两个极点时是否下一步是按规定走的,最后判断是否回到北。
#include<string>
#include<iostream>
using namespace std;
int main()
{
int n;
int i, j, k;
int x;
string str;
cin >> n;
int sum = 0;
bool pd = true;
for(i=1; i<=n; i++)
{
cin >> x >> str;
if(sum == 0 && str != "South"){
pd = false;
}
else if(sum == 20000 && str != "North"){
pd = false;
}
else if(str == "South")
{
if(sum >= 0 && sum < 20000){
if(x + sum > 20000){
pd = false;
}
else{
sum += x;
}
}
else{
if(sum - x < 20000){
pd = false;
}
else{
sum -= x;
}
}
}
else if(str == "North")
{
if(sum > 0 && sum <= 20000){
if(sum - x < 0){
pd = false;
}
else{
sum -= x;
}
}
else{
if(x + sum > 40000){
pd = false;
}
else{
sum += x;
if(sum == 40000){
sum = 0;
}
}
}
}
}
if(!pd || sum != 0){
cout << "NO\n";
}
else{
cout << "YES\n";
}
}
C. New Year and Rating
题意:
每场比赛有积分,处于>=1900参加div1,<1900参加div2,Limak今年参加了n场比赛,现给出每场比赛的轮次和比赛后的积分变化,问最后能获得的最大积分为多少。
思路:
从后往前,假设最后得分为x,根据第一组数据可列不等式
x - 8 <= 1899
x - 8 - 5 <= 1899
x - 8 - 5 + 7 >= 1900
#include<iostream>
using namespace std;
int array[200001][2];
const int INF = 1000000000;
const int FINF = -1000000000;
int main()
{
int i, j, k;
int n;
cin >> n;
for(i=1; i<=n; i++)
{
cin >> array[i][0] >> array[i][1];
}
int sum = 0;
int maxx = INF;
int minn = FINF;
for(i=n; i>=1; i--)
{
sum -= array[i][0];
if(array[i][1] == 2)
{
int t = 1899 - sum;
if(t < maxx){
maxx = t;
}
}
else{
int t = 1900 - sum;
if(t > minn){
minn = t;
}
}
}
if(maxx == INF){
cout << "Infinity\n";
}
else if(maxx < minn)
{
cout << "Impossible\n";
}
else{
cout << maxx << endl;
}
return 0;
}
D. New Year and Fireworks
题意:
放烟花,经下图n次迭代后最多多少个
思路:
记忆化搜索,首先注意到t<=5,且迭代次数<=30,因此数组最大300 * 300,定义状态dp[x][y][t][d],表示处于x行y列,迭代第t次,方向为d
int dict[8][2] = {{-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}};
//.......
dfs(x, y, t + 1, (d + 7) % 8);
dfs(x, y, t + 1, (d + 1) % 8);
每次递归方向为d-1和d+1
#include<iostream>
using namespace std;
int dict[8][2] = {{-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}};
int dp[310][310][31][9];
int array[310][310];
int value[31];
int n;
void dfs(int x, int y, int t, int d)
{
if(dp[x][y][t][d]){
return ;
}
if(t > n){
return;
}
int i;
dp[x][y][t][d] = 1;
for(i=0; i<value[t]; i++)
{
x += dict[d][0];
y += dict[d][1];
array[x][y] = 1;
}
dfs(x, y, t + 1, (d + 7) % 8);
dfs(x, y, t + 1, (d + 1) % 8);
}
int main()
{
int i, j, k;
cin >> n;
for(i=0; i<n; i++)
{
cin >> value[i];
}
dfs(151, 151, 0, 0);
int ans = 0;
for(i=1; i<310; i++)
for(j=1; j<310; j++)
{
if(array[i][j])
{
ans++;
}
}
cout << ans << endl;
}