指针
指针
前言:祝大家新年快乐哦!ヽ(✿゚▽゚)ノ
题目来源
今天的这道题来自于acwing
的一道周赛题,链接如下:
下面给出该题的题面
原题题面
给定一个如下图所示的全圆量角器。
初始时,量角器上的指针指向刻度 0。
现在,请你对指针进行 n
次拨动操作,每次操作给定一个拨动角度 ai
,由你将指针拨动 ai
度,每次的拨动方向(顺时针或逆时针)由你自由决定。
请你判断,能否通过合理选择每次拨动的方向,使得指针最终仍然指向刻度 0
输入格式
第一行包含整数 n
接下来 n
行,每行包含一个整数 ai
,表示一次操作的拨动角度。
输出格式
如果可以做到指针最终仍然指向刻度 0,则输出 YES
,否则输出 NO
。
数据范围
所有测试点满足 1 ≤ n
≤ 15,1 ≤ ai
≤ 180
输入样例1:
3
10
20
30
输出样例1:
YES
输入样例2:
3
10
10
10
输出样例2:
NO
输入样例3:
3
120
120
120
输出样例3:
YES
题目解释
优化思路
通过一系列的分析,我们可以大致得到一个思路,就是我们要灵活的计算出一个有效的方式,使得我们尽可能地使得我们的指针可以走回到0度或者说360度,不过吧,其实这道题和背包问题的一般思路是一样的,都分为取和不取,在背包问题里面,取和不取来分析在目前体积下可以达到的最大价值,而这道题就有些不同了,这道题是分为正向和反向,正向就当成取,反向就当成不取,因此我们可以同背包一样开一个二维数组,然后对于每一个方向都进行分析
首先,我们按照题目要求进行输入输出
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int f[N][361], v[N];
int main()
{
int n;
cin >> n;
for(int i = 1;i <= n;i++) cin >> v[i];
}
其次,我们对于f数组进行一个判断
//原点一定是对的,记为1
f[0][0] = 1;
for(int i = 1;i <= n;i++)
for(int j = 0;j <= 360;j++)
//正向取和反向取,满足一个就为1
f[i][j] = f[i - 1][(j + 360 + v[i]) % 360] || f[i - 1][(j + 360 - v[i]) % 360];
最后,我们按照题目要求输出结果
//360取模和0是一样的,所以这两个都可以
if(f[n][0] == 1 || f[n][360] == 1) cout << "YES" << endl;
//反之不行
else cout << "NO" << endl;
return 0;
如此一来,我们就解决这道题目啦!下面给出ac
代码
ac
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int f[N][360], v[N];
int main()
{
int n;
cin >> n;
for(int i = 1;i <= n;i++) cin >> v[i];
f[0][0] = 1;
for(int i = 1;i <= n;i++)
for(int j = 0;j <= 360;j++)
f[i][j] = f[i - 1][(j + 360 + v[i]) % 360] || f[i - 1][(j + 360 - v[i]) % 360];
if(f[n][0] == 1 || f[n][360] == 1) cout << "YES" << endl;
else cout << "NO" << endl;
return 0;
}
写在最后
本来是打算在除夕上午写的,但是由于各种原因,最后在新年的第一天才写,不过指针嘛,指向了一年的第一天,意味着新的一年的到来,祝大家新的一年多多进步,多敲代码,多多ac
哦!
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 浮云世事改, 过月此心明!