WAP笔试题

Wireless Routers

Description 题目如下

Alice just bought a very big house with N rooms and N-1 doors,which each door connects two rooms. Besides,each room have at least one door and at most 3 doors(of course Alice can go to every room in this house).
However, a modern person cannot live without WIFI, so Alice wants to put M wireless routers in several rooms. As the routers are cheap, only adjacent rooms(which have a door connect to this room) can receive it, and each router works independently.
Since M routers may cannot cover every room, Alice tells you the satisfaction point S[i] she could have if room i have WIFI.
Please Help Alice to calculate the maximum satisfaction point she can get to in total.

Input

The first line is two integers N(2<=2<=1000), M(1<=M<=N,M<=100) Then are N numbers, each shows the satisfaction S[i] (1<=S[i]<=10) point of room i. Then are N-1 lines, each contains two integer x,y, which represents a door is between room x and y.

Output

Just output the maximum point of satisfaction

Limits
  • Memory limit per test: 256 megabytes
  • Time limit per test:The faster then better

    Sample Test

    Input

    5 1
    1 2 3 4 5
    2 1
    3 2
    4 2
    5 3

    Output

    10

解题思想

首先明确一点,这是一个图的问题。这个房子抽象成一个图,图的每个顶点代表房间,顶点数N是房间数。 N-1 门就是图的边数。这是一个稀疏图,所以应该用邻接表去存。 M个路由器去覆盖房间以求最大的满意度,这是一个DP问题,显然求解两个路由器覆盖房间的最大满意度是包括了求解一个路由器覆盖方法的最大满意度。
抽象: S[i]= S[i-1]+x; // 就是说M个路由器的满意度肯定是建立在求出M-1个路由器的满意度的基础上。
最后就是可能不需要M个路由器就把所有房间都覆盖到了,此时就没有必要继续求解了。

代码如下:

package worksApplication;

import java.util.*;

public class Main{
    VNode[] adjlist;
    private int n;
    private int e;
    public static int MAXVERTEX=1010;
    public static int INFINITY=99999;
    public static int MINDATA=(-99999);
    private boolean[] visited;
    protected class ANode{
        int adjV;
        ANode nextArc;
        int weight;
    }
    protected class VNode{
        int Vertex;//
        ANode firstArc;
    }
    public Main(int n,int e){
        this.n=n;
        this.e=e;
        //path=new int[n+1];//
        //dist=new int[n+1];//distance or sum of weight between s and destination
        adjlist=new VNode[n];
        for(int i=0;i<n;i++)//from 1 to n,not 0!
            adjlist[i]=new VNode();

    }

    public boolean createGraph(Scanner s){
       // Scanner s=new Scanner(System.in);
        visited=new boolean[MAXVERTEX];
        ANode edge,edgex;
       for(int i=0;i<n;i++){
            int tmp=s.nextInt();
            if(tmp>=1&&tmp<=10)
            adjlist[i].Vertex=tmp;//satisfation point
            else{
                System.out.println("error input,out of range");
                return false;
            }
       }
        for(int i=0;i<n;i++){
            //dist[i]=INFINITY;//-1 not suitable for Dij
            adjlist[i].firstArc=null;
        }
        for(int k=0;k<e;k++){
            int m,d;
            m=s.nextInt()-1;d=s.nextInt()-1;//weight=s.nextInt()
            if(m<0||n<0)
                return false;
            edge=new ANode();
            edge.adjV=d;
            edge.nextArc=adjlist[m].firstArc;
            adjlist[m].firstArc=edge;

            //undirected graph
            edgex=new ANode();
            edgex.adjV=m;
            edgex.nextArc=adjlist[d].firstArc;
            adjlist[d].firstArc=edgex;
        }
        return true;
    }

    public boolean isConnected(){
        for(int i=0;i<n;i++)
            if(visited[i]==false)
                return false;
        return true;
    }

    public int subMaxEx(){
        int max=MINDATA;
        int index=-1;
        for(int i=0;i<n;i++) {
            ANode edge=adjlist[i].firstArc;
            if(visited[i])
                continue;//end i,because it already visied
            int sum=adjlist[i].Vertex;
            while(edge!=null){
                if(!visited[edge.adjV])
                {sum+=adjlist[edge.adjV].Vertex;}
                edge=edge.nextArc;
            }

            if(sum>max&&!visited[i]){
                max=sum;
                index=i;
            }

        }
        //only here we do the check
        visited[index]=true;
        ANode edgex=adjlist[index].firstArc;
        while(edgex!=null){
            visited[edgex.adjV]=true;
            edgex=edgex.nextArc;
        }
        return max;

    }

    public int findMaxSatisfaction(int routers){
        //initialize a table
        //int[] storage=new int[n];
        int maxSatisfaction=0;
        int M=0;//the number that routers cover all rooms
        /*for(int i=0;i<n;i++){
            ANode edge=adjlist[i].firstArc;
            int sum=adjlist[i].Vertex;
            while(edge!=null){
                sum+=adjlist[edge.adjV].Vertex;
                edge=edge.nextArc;
            }
            storage[i]=sum;
        }*/
        //Begining DP
        if(routers==1)
           // maxSatisfaction=subMax(storage);
           maxSatisfaction=subMaxEx();
        else{
            for(int k=0;k<routers;k++){
                //visited[]
                if(isConnected())
                {
                    M=k;//the graph already cover in M rounters
                    break;
                }
                maxSatisfaction+=subMaxEx();
            }
        }

        if(routers>=M&&M!=0){
            int sumx=0;
            for(int i=0;i<n;i++)
                sumx+=adjlist[i].Vertex;
            maxSatisfaction=sumx;
        }

        return maxSatisfaction;
    }

  public static void main(String[] args) {
     // TODO: Implement your program
    @SuppressWarnings("resource")
    Scanner s=new Scanner(System.in);
    int n=s.nextInt();
    int router=s.nextInt();
    int maxSatisfaction;
    if(n<2||n>1000||router<=0||router>n||router>100)
    {
        System.out.println("Out of range!");
        return;
    }
    int e=n-1;//n-1 lines
    Main g=new Main(n,e);
    if(!g.createGraph(s))
        return;
//    g.printPath();
    maxSatisfaction=g.findMaxSatisfaction(router);
    System.out.println(maxSatisfaction);
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值