【浮*光】洛谷0519五月月赛###全面解析###

15 篇文章 0 订阅

诶,悲惨世界吼...人生如此悲伤...

    我和老大的成绩...受伤ing...


A. 取石子 

题目:  Alice 和 Bob 在玩游戏。他们有 nn 堆石子,第 i堆石子有 aia_i 个,保证初始时 ai≤ai+1(1≤i<n)。现在他们轮流对这些石子进行操作,每次操作人可以选择满足 ai>ai−1a0 视为 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




                                                                                ——时间划过风的轨迹,那个少年,还在等你。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值