Damn Couples ZOJ - 3161

探讨了在一组特定条件下,如何通过优化选择顺序来最大化剩余人数的问题。使用递归思想预处理区间内的最优解,并通过排序和遍历操作实现高效求解。

传送门

题目大意

N个人,M组关系,每次选一种关系,如果两个人相邻,则任意删除其中一个,否则不变。问最坏情况下最多能剩多少人。

分析

为了留的人最多,我们可以先将原来不相邻的关系全部说完,这样我们只需要考虑以怎样的顺序说剩下的那些即可。由于剩下的关系可能被分成一段一段的,所以我们只需要预处理在一个均相连的区间内有k个人最坏情况最多剩下多少人即可。经过考虑我们发现从中间将这一组关系分成两段可以使结果最优,所以我们就得到了递推式子,详见代码。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define sp cout<<"---------------------------------------------------"<<endl;
int id[1100],cnt;
struct node {
      int x,y;
}d[1100];
inline bool cmp(const node a,const node b){
      return a.x<b.x;
}
int main(){
      int n,m,i,j,k=1,x,y;
      id[1]=0,id[2]=1,id[3]=2,id[4]=2;
      for(i=5;i<=500;i++)
        if(i%2)id[i]=id[(i-1)/2-1]+id[(i-1)/2+1]+1;
          else id[i]=id[i/2-1]+id[i/2]+1;
      while(scanf("%d%d",&n,&m)!=EOF){
      cnt=0;
      for(i=1;i<=m;i++){
          scanf("%d%d",&x,&y);
          if(y<x)swap(x,y);
          if(y-x!=1)continue;
          d[++cnt].x=x,d[cnt].y=y;
      }
      sort(d+1,d+cnt+1,cmp);
      int ans=n,len=1;
      d[0].y=d[1].x;
      for(i=1;i<=cnt;i++){
          if(d[i].x!=d[i-1].y)ans-=id[len],len=2;
            else len++;
      }
      ans-=id[len];
      cout<<ans<<endl;
      }
      return 0;
}

转载于:https://www.cnblogs.com/yzxverygood/p/9316181.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值