A - Birthday Cake
题意:给出一个圆,一些点,一些直线,问这些直线能否把圆分成诺干块,使得每一块上都有一个点
分析:先判断任意两个点是否被一条直线分开,在利用V+E+1=n判断
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#include <set>
using namespace std;
const int maxn = 100 + 7 ;
typedef pair<double, double> pii;
bool k[maxn][maxn];
struct Point{
int x,y;
}p[maxn];
struct Line {
int a,b,c;
}l[maxn];
int main(){
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int n,m,r;
cin>>n>>m>>r;
for(int i=1;i<=n;i++){
cin>>p[i].x>>p[i].y;
}
for(int i=1;i<=m;i++){
cin>>l[i].a>>l[i].b>>l[i].c;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(p[i].x*l[j].a+p[i].y*l[j].b+l[j].c>0)
k[i][j] = true;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
bool flag = false;
for(int h=1;h<=m;h++){
if(k[i][h]!=k[j][h]){
flag = true;
break;
}
}
if(!flag){
cout<<"no"<<endl;
return 0;
}
}
}
set<pii>ss;
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
if(i==j) continue;
int a1=l[i].a,b1=l[i].b,c1=l[i].c;
int a2=l[j].a,b2=l[j].b,c2=l[j].c;
if(a2*b1-a1*b2!=0){
double x = 1.0*(c1*b2-c2*b1)/(a2*b1-a1*b2);
double y = 1.0*(a2*c1-a1*c2)/(a1*b2-a2*b1);
if(x*x+y*y<r*r)
ss.insert(pii(x,y));
}
}
}
if(ss.size()+m+1==n) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
B - Bumped!
题意:给出一张无向图和边的权值,现在可以允许一条边的花费为零,求起点到终点的最小花费
分析:分层图最短
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#include <set>
#include <vector>
#include <cstring>
#include <queue>
#define FRER() freopen("in.txt","r",stdin);
#define FREW() freopen("out.txt","w",stdout);
#define mem(a,b) memset(a,b,sizeof(a));
using namespace std;
using namespace std;
typedef pair<int,int> pii;
const int maxn = 2e6 , inf = 0x3f3f3f3f;
int dp[maxn],res[maxn];
int a[maxn];
int main()
{
//FRER();
int n;
scanf("%d",&n);
for(int i=0;i<maxn;i++){
dp[i] = inf;
res[i] = 0;
}
dp[0] = 0;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
for(int j=a[i];j<maxn;j++)
dp[j] = min(dp[j],dp[j-a[i]]+1);
}
for(int i=1;i<maxn;i++){
int tmp = i;
for(int j=n;j>=1;j--){
res[i]+=tmp/a[j];
tmp%=a[j];
}
}
bool flag = true;
for(int i=1;i<maxn;i++){
if(dp[i]!=res[i]){
flag = false;
break;
}
}
printf("%s\n",flag?"canonical":"non-canonical");
}
C - Canonical Coin Systems
题意:给出货币发行的种类,是否能使得任意花费从最大面额的开始使用都能使用最少数量的钱币 (我也不知道在说啥
分析:dp跑一遍最小花费数量,贪心求一遍,两者比较一下。
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <deque>
#define ll long long
#define lowbit(x) (x&(-x))
#define mem(a,b) memset(a,b,sizeof(a))
#define FRER() freopen("in.txt","r",stdin);
#define FREW() freopen("out.txt","w",stdout);
using namespace std;
typedef pair<int,int> pii;
const int maxn = 2e6 + 7, inf = 0x3f3f3f3f;
int dp[maxn],res[maxn];
int a[maxn];
int main()
{
//FRER();
int n;
scanf("%d",&n);
mem(dp,inf);
mem(res,0);
dp[0] = 0;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
for(int j=a[i];j<maxn;j++){
dp[j] = min(dp[j],dp[j-a[i]]+1);
}
}
for(int i=1;i<maxn;i++){
int tmp = i;
for(int j=n;j>=1;j--){
res[i]+=tmp/a[j];
tmp%=a[j];
}
}
bool flag = true;
for(int i=1;i<maxn;i++){
if(dp[i]!=res[i]){
flag = false;
break;
}
}
printf("%s\n",flag?"canonical":"non-canonical");
}
D - Cat and Mice
E - Company Picnic
F - GlitchBot
模拟
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=50+10;
const char* str[]={"Left","Forward","Right"};
int dr[4][2]=
{
{0,1},
{1,0},
{0,-1},
{-1,0},
};
int tx,ty;
int n;
char buf[11];
int opr[N];
bool ok()
{
int nowx=0,nowy=0;
int flag=0;
for(int i=0;i<n;++i)
{
if(opr[i]==0)
{
nowx+=dr[flag][0];
nowy+=dr[flag][1];
}
else flag=(flag+4+opr[i])%4;
}
return nowx==tx&&nowy==ty;
}
void solve()
{
for(int i=0; i<n; ++i)
{
int oldopr=opr[i];
for(int j=-1; j<=1; ++j)
{
opr[i]=j;
if(ok())
{
printf("%d %s\n",i+1,str[j+1]);
return;
}
opr[i]=oldopr;
}
}
}
int main()
{
//freopen("i.txt","r",stdin);
scanf("%d%d%d",&tx,&ty,&n);
for(int i=0; i<n; ++i)
{
scanf("%s",buf);
if(buf[0]=='F')opr[i]=0;
else if(buf[0]=='R')opr[i]=1;
else if(buf[0]=='L')opr[i]=-1;
}
//for(int i=0; i<n; ++i)printf("%d\n",opr[i]);
solve();
return 0;
}
G - Greeting Card
题意:给出二维坐标平面上的点。求相距为2018的点的对数
分析:2018的勾股数只有(0,2018),(1680,1118)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll>pii;
const int maxn = 100000 + 7;
struct dir{
ll dx,dy;
}d[10];
struct Node{
ll x,y;
}no[maxn];
map<pii,int>mmp;
typedef pair<pii,pii>pp;
map<pp,int>mmmp;
int main()
{
//freopen("i.txt","r",stdin);
d[1].dx = 0 , d[1].dy = 2018;
d[2].dx = 1118 , d[2].dy = 1680;
d[3].dx = 1680 , d[3].dy = 1118;
d[4].dx = -1118 , d[4].dy = 1680;
d[5].dx = -1680 , d[5].dy = 1118;
d[6].dx = 2018 , d[6].dy = 0;
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld%lld",&no[i].x,&no[i].y);
pii p = make_pair(no[i].x,no[i].y);
mmp[p] = 1;
}
ll res = 0;
for(int i=1;i<=n;i++){
for(int j=1;j<=6;j++){
ll x = no[i].x+d[j].dx;
ll y = no[i].y+d[j].dy;
pii p1 = make_pair(x,y);
if(mmp[p1]){
res++;
}
}
}
cout<<res<<endl;
}
H - Imperfect GPS
I - Odd Gnome
题意:一个严格递增的序列中,出现了一个叛徒,这个叛徒不在第一个或者最后一个,找到他
分析:一个严格递增的序列中插入一个数,只可能出现两种情况破坏这个序列
1.插入的这个数比前一个还小
2.插入的这个数比后一个还大
找到这两个数分别验证
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 10000 + 7;
int a[maxn];
int n;
bool fun(int pos)
{
vector<int>v;
for(int i=1; i<=n; i++)
{
if(i==pos) continue;
v.push_back(a[i]);
}
for(int i=1; i<v.size()-1; i++)
{
if(v[i]>=v[i+1]) return false;
}
return true;
}
int main()
{
// freopen("i.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
int pos1 = 0, pos2 = 0;
for(int i=2; i<=n-1; i++)
{
if(a[i]<=a[i-1])
pos1 = i;
if(a[i]>=a[i+1])
pos2 = i;
}
//cout<<pos1<<" "<<pos2<<endl;
if(pos1)
{
if(fun(pos1))
{
cout<<pos1<<endl;
continue;
}
}
if(pos2)
{
if(fun(pos2))
{
cout<<pos2<<endl;
continue;
}
}
cout<<2<<endl;
}
}
J - Progressive Scramble
题意:给一个字符串,输出加密或者解密之后的字符串
每一条消息仅包含小写字母和空格.我们认为空格的值为0,字母的值对应于其在字母表中的值.(a对应1,z对应26)
加密方式如下:
以"my pie"为例.
1.求出每一个字母的值的数组[13,25,0,16,9,5].
2.从第一个元素开始,每一个元素u[i] = u[i-1] + u[i].得到[13,38,38,54,63,68].
3.将每一个元素对27取余,得到[13,11,11,0,9,14].
4.最后将其与字母表的顺序值和空格的值对应反编码得到"mkk in".
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=80+10;
char s[N];
int a[N],n;
void solve(char ch)
{
if(ch=='e')
{
for(int i=0;i<n;++i)a[i]=!isspace(s[i])?s[i]-'a'+1:0;
for(int i=1;i<n;++i)a[i]+=a[i-1];
for(int i=0;i<n;++i)a[i]%=27;
for(int i=0;i<n;++i)s[i]=a[i]?a[i]+'a'-1:' ';
}
else if(ch=='d')
{
for(int i=0;i<n;++i)a[i]=!isspace(s[i])?s[i]-'a'+1:0;
for(int i=n-1;i>=1;--i)a[i]-=a[i-1];
for(int i=0;i<n;++i)a[i]=((a[i]%27)+27)%27;
for(int i=0;i<n;++i)s[i]=a[i]?a[i]+'a'-1:' ';
}
}
int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
char ch;
scanf(" %c%*c%[^\n]",&ch,s);
n=strlen(s);
solve(ch);
puts(s);
}
return 0;
}