诶,悲惨世界吼...人生如此悲伤...
我和老大的成绩...受伤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