2 条题解

  • 0
    @ 2025-10-8 17:02:57
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=1e6+10, inf=1e9;
    LL n, ans, sum, x[N], y[N], m[N], v[N], st[N];
    void solve(LL lx, LL rx, LL ly, LL ry) {
        sum=0;
        for(int i=1;i<=n;i++) {
            if(lx <= x[i] && rx >= x[i] && ly <= y[i] && ry >= y[i]) {v[i]=0; continue;} //如果不在范围内就不管 
            if(lx <= y[i] && rx >= y[i] && ly <= x[i] && ry >= x[i]) {v[i]=1; sum+=m[i];} //如果在则加上 
            else return ; //不可能更优,排除 
        }
        if(sum < ans) {ans=sum; for(int i=1;i<=n;i++) st[i]=v[i];} //更新答案 
    }
    int main() {
        scanf("%d", &n);
        LL lx=inf, rx=0, ly=inf, ry=0;
        //为了使lx!=ly,rx!=ry,我们定义min(x[i],y[i])为横坐标,max(x[i], y[i])为纵坐标 
        //即lx<ly, rx<ry 
        //lx表示最小的横坐标,ly表示最大的纵坐标中最小的 (rx,ry同理)
        //即求出边界的4个点
        //从右至左,上至下依次为
        //(lx, rx), (lx, ry)
        //(ly, rx), (ly, ry) 
        for(int i=1;i<=n;i++) {
            scanf("%d%d%d", &x[i], &y[i], &m[i]);
            lx=min(lx, min(x[i], y[i])), rx=max(rx, min(x[i], y[i]));
            ly=min(ly, max(x[i], y[i])), ry=max(ry, max(x[i], y[i]));
        }
        printf("%lld ", 2*(rx+ry-lx-ly));
        ans=inf;
        //尝试是否可以翻折  
        //对角线逐一对应 (考虑将所有点翻折到y=x的一边) 
        solve(lx, rx, ly, ry); 
        solve(lx, ry, ly, rx);
        solve(ly, rx, lx, ry); 
        solve(ly, ry, lx, rx);
        printf("%lld\n", ans);
        for(int i=1;i<=n;i++) printf("%lld", st[i]);
        return 0;
    }
    
    • 0
      @ 2025-10-8 17:02:44
      #include<bits/stdc++.h>
      using namespace std;
      typedef long long LL;
      const int N=1e6+10, inf=1e9;
      LL n, ans, sum, x[N], y[N], m[N], v[N], st[N];
      void solve(LL lx, LL rx, LL ly, LL ry) {
      	sum=0;
      	for(int i=1;i<=n;i++) {
      		if(lx<=x[i]&&rx>=x[i]&&ly<=y[i]&&ry>=y[i]) {v[i]=0; continue;} //如果不在范围内就不管 
      		if(lx<=y[i]&&rx>=y[i]&&ly<=x[i]&&ry>=x[i]) {v[i]=1; sum+=m[i];} //如果在则加上 
      		else return ; //不可能更优,排除 
      	}
      	if(sum<ans) {ans=sum; for(int i=1;i<=n;i++) st[i]=v[i];} //更新答案 
      }
      int main() {
      	scanf("%d", &n);
      	LL lx=inf, rx=0, ly=inf, ry=0;
      	//为了使lx!=ly,rx!=ry,我们定义min(x[i],y[i])为横坐标,max(x[i], y[i])为纵坐标 
      	//即lx<ly, rx<ry 
      	//lx表示最小的横坐标,ly表示最大的纵坐标中最小的 (rx,ry同理)
      	//即求出边界的4个点
      	//从右至左,上至下依次为
      	//(lx, rx), (lx, ry)
      	//(ly, rx), (ly, ry) 
      	for(int i=1;i<=n;i++) {
      		scanf("%d%d%d", &x[i], &y[i], &m[i]);
      		lx=min(lx, min(x[i], y[i])), rx=max(rx, min(x[i], y[i]));
      		ly=min(ly, max(x[i], y[i])), ry=max(ry, max(x[i], y[i]));
      	}
      	printf("%lld ", 2*(rx+ry-lx-ly));
      	ans=inf;
      	//尝试是否可以翻折  
      	//对角线逐一对应 (考虑将所有点翻折到y=x的一边) 
      	solve(lx, rx, ly, ry); 
      	solve(lx, ry, ly, rx);
      	solve(ly, rx, lx, ry); 
      	solve(ly, ry, lx, rx);
      	printf("%lld\n", ans);
      	for(int i=1;i<=n;i++) printf("%lld", st[i]);
      	return 0;
      } 
      • 1

      「POI2007 R2」石头花园 Rock Garden

      信息

      ID
      2758
      时间
      3500ms
      内存
      64MiB
      难度
      7
      标签
      递交数
      23
      已通过
      8
      上传者