【牛客】小白月赛99——F 自爆机器人

复盘:

  • 当时看到第一眼觉得是个贪心,但不知道怎么使得结果最大
  • 看完解题才知道是个披着羊皮的狼–完全背包

思路:

根据题目的意思 机器人到终点最少时间就是n(0为起点 n为终点)

  • 如果 爆炸时间t小于n就代表不能炸掉妖怪输出0 return返回
  • 其次可建墙壁的位置个数如果是1就不用考虑建墙壁 直接输出n就好了 因为建一个墙壁方向回不来
  • 建墙壁至少是以来回为单位的 所有 两墙壁的距离乘2存于数组中备用
  • 所有先假设跑完n后再加入 过程中来回徘徊的(可以徘徊无数次 只要在t的范围内)
  • 因此就是 背包容量大小为t-n 最多可以放多少大小为俩墙壁距离的物品 最后输出最大结果加回原来的n

ACcode

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+3;
int tt,n,m,t;
int num[N];
int main(){
	cin>>tt;
	while(tt--){
		cin>>n>>m>>t;
       
        t-=n;//背包的大小
        vector<int> v(m+1);
        for(int i=1;i<=m;i++){
        	cin>>v[i];
        }
        sort(v.begin() + 1, v.end());
        if(t<0){//走不到先炸开了
        	cout<<0<<endl;
        	continue;
        }
        if(m<=1){//一个墙壁无效果
        	cout<<n<<endl;
        	continue;
        }
        set<int> s;
        for(int i=2;i<=m;i++){
        	s.insert(2*(v[i]-v[i-1]));
        }
        //完全背包模板
        vector<bool> dp(t+1);
        dp[0]=1;
        for(auto val:s){
        	for(int i=val;i<=t;i++){
        		dp[i]=dp[i]|dp[i-val];//倍数才true
        	}
        }
        for(int i=t;t>=0;i--){
        	if(dp[i]!=0)
        	{
	        	cout<<i+n<<endl;
	        	break;	
        	} 
        }
        
        
		
	}
	return 0;
}

核心代码解释

  dp[0]=1;
  for(auto val:s){
   	for(int i=val;i<=t;i++){
   		dp[i]=dp[i]|dp[i-val];//倍数才true   
   	}
   }
```

*  就是判断是否能遍历到这个值   dp[i]=dp[i]|dp[i-val];
*  按位或就是其中一个为true  dp【i】 就为true【i-val] 如果出现了 就必然能出现i  因为当前就是在遍历val的倍数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值