zoukankan      html  css  js  c++  java
  • hust Dating With Girls

    http://acm.sdibt.edu.cn:8080/judge/contest/view.action?cid=573#problem/B

    题意:求最大权值和,起点为1,终点为权值最大的那个点(其权值为负,而且在负数里最大),这题同时要求在到达负最大的权值那个点之前不能经过其他负数的点,

              而且没经过一个点,就加上该点的wi,最后一个点也要加上|wi|

    分析:刚开始我是搜索,纯搜,毫无疑问超时~~~

             后来实在无法,搜了解题报告发现是记忆化搜索,不过自己敲出来一直wa,纠结了好久后才知道,原来在取可连通路径最大值那里错了

     记忆化搜索

    View Code
    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    const int MN=110;
    const int INF=0x7fffffff;
    int map[MN][MN];
    int num[MN];
    int dp[MN];
    int n,m;
    int MIN;
    int ans;
    int e;
    
    int DFS(int cur)
    {
        if(dp[cur]>=0) return dp[cur];
        if(cur==e) return -MIN;
        if(num[cur]==-INF) return 0;
        int MAX=0;
        for(int i=1; i<=n; i++)
        {
            if(cur==i) continue;
            if(map[cur][i])
            {
                int tmp=DFS(i);
                if(tmp>0) MAX=max(MAX,num[cur]+tmp);
                //这里的tmp>0必须要有,因为当路径不可达的情况下
                //递归所返回的值是0,而num[cur]>0这样必定比MAX=0
                //大,而其i点本身不可达,又哪来的比较
            }
        }
        return dp[cur]=MAX;
    }
    
    int main()
    {
        int i,j,a,b;
        int flag;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            flag=false;
            memset(map,0,sizeof(map));
            memset(dp,-1,sizeof(dp));
            for(i=1; i<=m; i++)
            {
                scanf("%d%d",&a,&b);
                map[a][b]=1;
            }
            MIN=99999;
            num[1]=0;
            for(i=2; i<=n; i++)
            {
                scanf("%d",&num[i]);
                if(num[i]<0)
                {
                    flag=true;
                    if(MIN>num[i])
                    {
                        MIN=num[i];
                        e=i;
                    }
                }
            }
            for(i=2;i<=n;i++)
            {//将所有小于最大负数的点赋予无穷,不可达
                if(num[i]<0 && num[i]>MIN) num[i]=-INF;
            }
            ans=DFS(1);
            if(ans==0 || flag==false) printf("What is a fucking day!\n");
            else printf("%d\n",ans);
        }
        return 0;
    }

    BFS

    View Code
    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    #include<queue>
    
    using namespace std;
    const int MN=110;
    const int INF=0x7fffffff;
    int map[MN][MN];
    int num[MN];
    int mmax[MN];
    int vis[MN];
    int n,m;
    int MIN;
    int e;
    
    int BFS(int e)
    {
        int i,j;
        memset(vis,0,sizeof(vis));
        memset(mmax,-1,sizeof(mmax));
        queue<int>Q;
        Q.push(1);
        vis[1]=0;
        mmax[1]=0;
        while(!Q.empty())
        {
            int head=Q.front();
            Q.pop();
            for(i=1; i<=n; i++)
            {
                if(map[head][i])
                {
                    if(num[i]>0)//这里加上vis==0是错的
                    {//因为vis的作用只是判断点是否进过队列
                        if(mmax[i]<mmax[head]+num[i])
                            mmax[i]=mmax[head]+num[i];
                    }
                    if(i==e)
                    {
                        if(mmax[i]<mmax[head]-num[i])
                            mmax[i]=mmax[head]-num[i];
                    }
                    if(num[i]>0 && vis[i]==0)
                    {
                        Q.push(i);
                        vis[i]=1;
                    }
                }
            }
            vis[head]=0;
        }
    }
    
    int main()
    {
        int i,j,a,b;
        int flag;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            flag=false;
            memset(map,0,sizeof(map));
            for(i=1; i<=m; i++)
            {
                scanf("%d%d",&a,&b);
                map[a][b]=1;
            }
            MIN=99999;
            num[1]=0;
            for(i=2; i<=n; i++)
            {
                scanf("%d",&num[i]);
                if(num[i]<0)
                {
                    flag=true;
                    if(MIN>num[i])
                    {
                        MIN=num[i];
                        e=i;
                    }
                }
            }
            for(i=2; i<=n; i++)
            {
                //将所有小于最大负数的点赋予无穷,不可达
                if(num[i]<0 && num[i]>MIN) num[i]=-INF;
            }
            BFS(e);
            if(mmax[e]>0) printf("%d\n",mmax[e]);
            else printf("What is a fucking day!\n");
        }
        return 0;
    }
  • 相关阅读:
    在C#中运用SQLDMO备份和恢复SQL Server数据库(转)
    c#中分割字符串的几种方法
    MS SQL Server中的日期格式化大全
    IBM基于双机热备份配置
    C#实现Des加密和解密
    ASP.NET备份恢复SqlServer数据库
    WEB 打印的相关技术分析
    通过身份证号码取得生日的一段代码(支持18位和15位身份证)
    C#的四种排序算法
    .net下读写配置文件app.config方法
  • 原文地址:https://www.cnblogs.com/zsboy/p/2952025.html
Copyright © 2011-2022 走看看