诶,悲惨世界吼...人生如此悲伤...
我和老大的成绩...受伤ing...
A. 取石子
题目: Alice 和 Bob 在玩游戏。他们有
nn 堆石子,第
i堆石子有
aia_i 个,保证初始时
ai≤ai+1(1≤i<n)。现在他们轮流对这些石子进行操作,每次操作人可以选择满足
ai>ai−1(
a0 视为
00)的一堆石子,并从中取走一个。谁最后不能取了谁输。Alice 先手,他们都使用最优策略,请判断最后谁会取得胜利。
分析:最后所有的石子肯定会被选完,而每次每个人选一个,所以石子的总和为奇数则先手赢,否则后手赢。
#include<bits/stdc++.h>
using namespace std;
/* 【取石子】
他们有 n 堆石子,第i堆石子有 ai个,保证初始时 ai≤ai+1(1≤i<n)
现在他们轮流对这些石子进行操作,每次操作人可以选择满足 ai>ai−1
( a0视为 0 )的一堆石子,并从中取走一个。
谁最后不能取了谁输。Alice 先手,他们都使用最优策略,请判断最后谁会取得胜利。*/
const int maxn=100000009;
bool okk[maxn];//ai>ai−1
int a[maxn];
int main(){
int n,sum=0; cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]); sum+=a[i]%2;//最终都是0
}
if(sum%2==0) printf("Bob\n");
else printf("Alice\n");
return 0;
}
B.偷上网
题目:Alice 和 Bob 生活在一个
l×l的正方形房子里,由于 Bob 最近沉迷隔膜,Alice 决定要限制 Bob 上网的频率。
Alice 建造了n个无线信号屏蔽器,第 i个位于 (xi,yi),屏蔽范围为 ln 。去寻找一个位置 (x,y)没有被 Alice 的屏蔽器覆盖。
分析:如果 n=1,则枚举一下四个角,如果都不可行,一定无解,否则就找到了合法点。
如果 n≥2,则圆的总面积一定小于正方形的面积,每次随机一个点,判断是否可行。显然随机次数不会太多就会找到合法解。
---> rand有一个最大值是rand_max,用随机到的数 x/rand_max * 范围l就行了,
当前随机到的占总共的比例乘范围就是想要的数。
对于整数来说随机[x,y] rand()%(y-x+1)+x; 小数就是[0,range] ((double)rand()/RAND_MAX)*range
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<ctime>
#define delta 1e-6
using namespace std;
int n,l;
bool ok;
double r;
struct circle{
double x,y;
}pos[11];
double getdis(double x1,double y1,double x2,double y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
bool judge(double x,double y){
for(int i=1;i<=n;i++){
if(getdis(pos[i].x,pos[i].y,x,y)<r+delta) return false;
}
return true;
}
int main(){
srand(time(NULL));
cin>>n>>l; r=l/n;
for(int i=1;i<=n;i++)cin>>pos[i].x>>pos[i].y;
for(int i=1;i<=5000;i++){
double nx=((double)rand()/RAND_MAX)*l;
double ny=((double)rand()/RAND_MAX)*l;
if(judge(nx,ny)){
cout<<nx<<" "<<ny;
return 0;
}
}
cout<<"GG";
return 0;
} //来自 https://blog.csdn.net/u014296725/article/details/80381654 感谢大佬qwq
分析:1. 除非起点就是特殊点,要不然不可能会GG。
2.考虑建边,对于所有的点,我们向它
有可能可以到达的点建边,边权就是固定这个骨牌的代价。
3.因为每一个骨牌都可以连出两条边,并且不可能有环,所以是树;然后就要求最小的代价割掉所有点,考虑树形DP
4.设f[x]表示割掉x及其所有字数中的特殊点的最小代价,则
f[x]=v[fa[x]][x] (if x is a special node)
f[x]=Σmin(v[x][son[x]],f[son[x]]) ( if x is a common node)
发现这个建图可以和DP的过程一起写成一个类似记搜的方法
#include<cstdio>
using namespace std;
const int N=1005,fx[4]={0,1,0,-1},fy[4]={1,0,-1,0};
int a[N][N],c[N*N],n,m,k,t,x,y,s_x,s_y;
bool sp[N][N];
inline char tc(void){
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x){
x=0; char ch=tc();
while (ch<'0'||ch>'9') ch=tc();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
}
inline long long min(long long a,long long b){
return a<b?a:b;
}
inline bool check(int x,int y){
return x>=1&&x<=n&&y>=1&&y<=m;
}
inline long long DFS(int x,int y){
long long ans=0;
for (register int i=0;i<4;++i){
int xx=x+fx[i]*2,yy=y+fy[i]*2;
if (check(xx,yy)&&a[x+fx[i]][y+fy[i]]==a[xx][yy]){
if (sp[xx][yy]) ans+=c[a[xx][yy]];
else ans+=min(DFS(xx,yy),c[a[xx][yy]]);
}
}
return ans;
}
int main(){
register int i,j;
read(n); read(m); read(k); t=n*m-1>>1;
for (i=1;i<=t;++i)
read(c[i]);
for (i=1;i<=k;++i)
read(x),read(y),sp[x][y]=1;
for (i=1;i<=n;++i)
for (j=1;j<=m;++j){
read(a[i][j]);
if(!a[i][j]) s_x=i,s_y=j;
}
if (sp[s_x][s_y]) puts("GG");
else printf("%lld",DFS(s_x,s_y));
return 0;
} //来自 https://www.cnblogs.com/cjjsb/p/9076443.html 膜拜dalao