2 条题解

  • 0
    @ 2025-10-8 16:55:44

    思路简述: 因为导弹来临是按照顺序,而非高度,所以我们绝对不能用 sort(显而易见)。

    那么我们不妨将每个导弹分个类: 1、可以用某个上升拦截系统拦截。 2、可以用某个下降拦截系统拦截。 3、需要新建一个上升拦截系统拦截。 4、需要新建一个下降拦截系统拦截。 考虑其中 1 跟 2,3 跟 4 是相互矛盾的,所以我们可以剪枝优化。

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=55;
    int n,ans;
    int a[MAXN];
    vector<int> up,down;//up存上升系统,down存下降系统
    void dfs(int now)//现在正在拦截第now个导弹
    {
    	int upsize=up.size();//注意:千万不要把它俩定义成全局变量!!血泪教训
    	int downsize=down.size();//注意:千万不要把它俩定义成全局变量!!血泪教训
    	if(upsize+downsize>=ans) return;//上述剪枝
    	if(now>n)
    	{
    		ans=min(ans,upsize+downsize);//上述剪枝
    //		printf("over ans:%d\n",ans);
    		return;
    	}
    	for(int i=0;i<upsize;i++)//开始枚举每个上升系统
    	{
    		if(up[i]<a[now])//可以拦截
    		{
    			int t=up[i];//t也不可以定义为全局变量!!
                //dfs回溯备份
    			up[i]=a[now];
    			dfs(now+1);//继续拦截下一个
    			up[i]=t;
    			break;
    		}
    	}
    	if(upsize==0||up[upsize-1]>=a[now])//判断,是否需要新开一个上升系统
    	{
    		up.push_back(a[now]);
    		dfs(now+1);
    		up.pop_back();
    	}
    	//同上,ctrl C,ctrl V
    	//说实话,我因为复制完漏了更改名字而调了半天,太蒻了
    	for(int i=0;i<downsize;i++)
    	{
    		if(down[i]>a[now])
    		{
    			int t=down[i];
    			down[i]=a[now];
    			dfs(now+1);
    			down[i]=t;
    			break;
    		}
    	}
    	if(downsize==0||down[downsize-1]<=a[now])
    	{
    		down.push_back(a[now]);[DFS]
    		dfs(now+1);
    		down.pop_back();
    	}
    	return;
    }
    int main(){
    	while (true)
    	{
    		scanf("%d",&n);
    		if(n==0) break;//虽然题目没说,但由样例可知,n=0时结束
    		up.clear();
    		down.clear();
    		for(int i=1;i<=n;i++)
    			scanf("%d",&a[i]);
    		ans=0x7fffffff;//无穷大
    		dfs(1);
    		printf("%d\n",ans);
    	}
    	return 0;
    }
    
    • 0
      @ 2025-10-8 16:55:23
      /*
      思路简述:
      因为导弹来临是按照顺序,而非高度,所以我们绝对不能用 sort(显而易见)。
      
      那么我们不妨将每个导弹分个类:
      1、可以用某个上升拦截系统拦截。
      2、可以用某个下降拦截系统拦截。
      3、需要新建一个上升拦截系统拦截。
      4、需要新建一个下降拦截系统拦截。
      考虑其中 1 跟 2,3 跟 4 是相互矛盾的,所以我们可以剪枝优化。
      
      剪枝代码:
      int upsize=up.size();
      int downsize=down.size();
      if(upsize+downsize>=ans) return;//这种情况已经超过或赶上之前我的最优方案了,我还留你干嘛
      if(now>n)//全部拦截后
      {
      	ans=min(ans,upsize+downsize);//上升下降的总套数
      //	printf("over ans:%d\n",ans);
      	return;
      }
      */
      #include<bits/stdc++.h>
      using namespace std;
      const int MAXN=55;
      int n,ans;
      int a[MAXN];
      vector<int> up,down;//up存上升系统,down存下降系统
      void dfs(int now)//现在正在拦截第now个导弹
      {
      	int upsize=up.size();//注意:千万不要把它俩定义成全局变量!!血泪教训,调了1小时
      	int downsize=down.size();//注意:千万不要把它俩定义成全局变量!!血泪教训,调了1小时
      	if(upsize+downsize>=ans) return;//上述剪枝
      	if(now>n)
      	{
      		ans=min(ans,upsize+downsize);//上述剪枝
      //		printf("over ans:%d\n",ans);
      		return;
      	}
      	for(int i=0;i<upsize;i++)//开始枚举每个上升系统
      	{
      		if(up[i]<a[now])//可以拦截
      		{
      			int t=up[i];//t也不可以定义为全局变量!!
                  //dfs回溯备份
      			up[i]=a[now];
      			dfs(now+1);//继续拦截下一个
      			up[i]=t;
      			break;
      		}
      	}
      	if(upsize==0||up[upsize-1]>=a[now])//判断,是否需要新开一个上升系统
      	{
      		up.push_back(a[now]);
      		dfs(now+1);
      		up.pop_back();
      	}
          //同上,ctrl C,ctrl V
          //说实话,我因为复制完漏了更改名字而调了半天,太蒻了
      	for(int i=0;i<downsize;i++)
      	{
      		if(down[i]>a[now])
      		{
      			int t=down[i];
      			down[i]=a[now];
      			dfs(now+1);
      			down[i]=t;
      			break;
      		}
      	}
      	if(downsize==0||down[downsize-1]<=a[now])
      	{
      		down.push_back(a[now]);
      		dfs(now+1);
      		down.pop_back();
      	}
      	return;
      }
      int main(){
      	while (True)
      	{
      		scanf("%d",&n);
      		if(n==0) break;//虽然题目没说,但由样例可知,n=0时结束
      		up.clear();
      		down.clear();
      		for(int i=1;i<=n;i++)
      			scanf("%d",&a[i]);
      		ans=0x7fffffff;//无穷大
      		dfs(1);
      		printf("%d\n",ans);
      	}
      	return 0;
      }
      • 1

      0x20搜索(练习)5:*Missile Defence System

      信息

      ID
      1102
      时间
      3000ms
      内存
      128MiB
      难度
      7
      标签
      递交数
      149
      已通过
      30
      上传者