题目链接:https://vjudge.net/problem/Gym-101190J
解题思路:
这题直接暴力模拟求每层的重心(质量和位置有关),看前i层的物体重心是否落在第i+1层的实体上,没有的话就一定倒了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int mx = 1e4 + 10;
int n, w, h, m;
int cnt[mx];
int suf[mx];
double dx[mx],dy[mx],sum[mx];
double midx[mx],midy[mx];
int l[mx],r[mx];
bool vis[mx/2][mx];
int main()
{
freopen("jenga.in", "r", stdin);
freopen("jenga.out", "w", stdout);
scanf("%d%d%d%d",&n,&w,&h,&m);
for(int i=h;i;i--){
sum[i] = 1.0*n*n/2;
cnt[i] = n,suf[i] = suf[i+1] + n;
dy[i] = dx[i] = 1.0*n/2;
midx[i] = (dx[i]*(suf[i]-suf[i+1])+midx[i+1]*suf[i+1])/suf[i];
midy[i] = (dy[i]*(suf[i]-suf[i+1])+midy[i+1]*suf[i+1])/suf[i];
l[i] = 1,r[i] = n;
}
int a,b;
for(int i=1;i<=m;i++){
scanf("%d%d",&a,&b);
sum[a] -= b - 0.5,cnt[a]--;
vis[a][b] = 1;
if(a&1) dx[a] = sum[a] / cnt[a];
else dy[a] = sum[a] / cnt[a];
while(vis[a][l[a]]&&l[a]<=r[a]) l[a]++;
while(vis[a][r[a]]&&l[a]<=r[a]) r[a]--;
for(int j=a;j;j--){
suf[j]--;
midx[j] = (dx[j]*(suf[j]-suf[j+1])+midx[j+1]*suf[j+1])/suf[j];
midy[j] = (dy[j]*(suf[j]-suf[j+1])+midy[j+1]*suf[j+1])/suf[j];
if(j!=h){
if(j&1){
if(midx[j+1]<=l[j]-1||midx[j+1]>=r[j])
return 0*printf("yes\n%d\n",i);
}else{
if(midy[j+1]<=l[j]-1||midy[j+1]>=r[j])
return 0*printf("yes\n%d\n",i);
}
}
}
}
return 0*puts("no");
}