• 2012 多校联合比赛第二场


    1009   

    直接贪心。类似于SPFA

    算法。我们要求损耗最小,也就是剩余最大。对于每个节点,我们记录起当前可以达到的剩余最大电力。和 Dijkstra算法相似,我们这里每次找寻的是尚未标记的拥有最大值的结点,并把这个最大值作为当前结点的最终结果,标记此结点并通过当前结点拓展与之 相连的结点。因为从一个结点传输电力到另一个几点,电力的总量是不会增加的。所以,在以后的贪心过程中,不会更新之前已经标记的结点,因为不可能有更大的 值。

    这样只要求得最后到达t的最大剩余电力就能得出答案。

    View Code
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<queue>
    #include<vector>
    #include<string>
    #define Min(a,b) a<b?a:b
    #define Max(a,b) a>b?a:b
    #define CL(a,num) memset(a,num,sizeof(num));
    #define maxn  50200
    #define inf 9999999
    using namespace std;
    struct node
    {
        int k;
        int cost;
    
        node(int x,int y):k(x),cost(y){}
    
    };
    vector<node>p[maxn];
    struct cnode
    {
        int k;
        double w;
    
        cnode (int x,double y ) :k(x),w(y){}
    
    };
    queue<cnode>que;
    int s,t,n;
    double ans;
    int vis[maxn];
    double pow;
    double f[maxn];
    void init()
    {
        for(int i=0;i<=n;i++)
        {
            p[i].clear();
            vis[i]=0;
            f[i]=-1;
        }
        ans=-1;
    }
    void SPFA()
    {
        int i;
        while(!que.empty())que.pop();
        que.push(cnode(s,pow));
    
         vis[s]=1;
         f[s]=pow;
    
        while(!que.empty())
        {
    
            cnode a=que.front();que.pop();
            int k=a.k;
            double w=a.w;
    
             vis[k]=0;
             for(i=0;i<p[k].size();i++)
            {
                node b=p[k][i];
                double t=f[k] - f[k]*b.cost/100.0;
                if(t>f[b.k])
                {
    
                     f[b.k]=t;
    
    
    
                      if(!vis[b.k])
                      { que.push(cnode(b.k,f[b.k])) ;
                        vis[b.k]=1;
                      }
    
    
    
    
    
                }
    
    
    
    
            }
        }
    }
    int  main()
    {
        //freopen("in.txt","r",stdin);
    
        int i,a,x,y;
        while(scanf("%d",&n)!=EOF)
        {
            init();
            for(i=1;i<=n;i++)
            {
                 scanf("%d",&a);
                 while(a--)
                 {
                     scanf("%d%d",&x,&y);
                     p[i].push_back(node(x,y));
    
                 }
            }
            scanf("%d%d%lf",&s,&t,&pow);
    
            BFS();
    
            if(f[t]==-1)printf("IMPOSSIBLE!\n");
            else printf("%.2lf\n",pow-f[t]);
        }
    }

    4310   Hero  

    http://acm.hdu.edu.cn/showproblem.php?pid=4310   

    此题官方的解题报告是 状态压缩dp,不过贪心 也能过
    今天用 状态压缩dp 做了一下,对状态压缩 dp 有了进一步的了解
    有转移方程dp[mask] = min{dp[mask - {i}] + hp_sum[mask] * dps[i], for all i in mask}

    View Code
     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 #include<set>
     8 #include<map>
     9 #define Min(a,b)  a>b?b:a
    10 #define Max(a,b)  a>b?a:b
    11 #define CL(a,num)  memset(a,num,sizeof(a));
    12 #define inf 9999999
    13 #define maxn 200000
    14 using namespace std;
    15 int dp[1<<20],sum[1<<20];
    16 struct node
    17 {
    18     int dps;
    19     int hp;
    20 }p[30];
    21 int main()
    22 {
    23     int n,i,s;
    24     while(scanf("%d",&n)!=EOF)
    25     {
    26         for(i=0;i<n;i++)
    27           scanf("%d%d",&p[i].dps,&p[i].hp);
    28           CL(sum,0);
    29         for(s=0;s<(1<<n);s++)
    30         {
    31             for(i=0;i<n;i++)
    32              {
    33                  if(s&(1<<i))sum[s]+=p[i].hp;
    34              }
    35         }
    36         for(s=0;s<1<<n;s++)
    37              dp[s]=inf;
    38              
    39              
    40         dp[0]=0;
    41         for(s=0;s<(1<<n);s++)
    42         {
    43             for(i=0;i<n;i++)
    44             {
    45                 if(s&(1<<i))continue;
    46                 int t=1<<i;
    47                 dp[s+t]=Min(dp[s+t],dp[s]+sum[s+t]*p[i].dps);
    48             }
    49         }
    50           int k=1<<n;
    51          cout<<dp[k-1]<<endl;
    52     }
    53 }

     4311  

    Meeting point-1

    题意:在二维图中 给出n个点的坐标,求出,其中一点使得 其他点到达 这个距离最短(只能上下左右的走)

    官方题解:

    Meeting point-1:

    平面上两点间的 Manhattan 距离为 |x1-x2| + |y1-y2|

    X 方向的距离与 Y 方向上的距离可以分开来处理。假设我们以 (xi,yi) 作为开会的地点,那么其余的点到该开会地点所需的时间为 X 方向上到 xi 所需要的时间加上 Y 方向上到 yi 所需要的时间。

    对数据预处理后可以快速地求出x坐标小于xi的点的个数rankx, 并且这些 x 坐标值之和 sumx,那么这些点 X 方向上对结果的贡献为 rankx * xi - sumx;同理可以处理出 x 坐标大于 xi 的点在 X 方向上对结果的贡献值。同理可求得其余点在 Y 方向上到达 yi 所需要的总时间。

    View Code
    #include<cstdio>
    #include<queue>
    #include<iostream>
    #include<vector>
    #include<map>
    #include<algorithm>
    #include<cmath>
    #define Min(a,b) a<b?a:b
    #define maxn  200000
    #define inf 0x7fffffff
    typedef long long ll;
    using namespace std;
    struct Point{
        int x, y;
        Point(){}
        Point(int _x, int _y):x(_x),y(_y){}
    }ary[maxn];
    
    
    
    ll sx[maxn],sy[maxn],x[maxn],y[maxn];
    int main()
    {
       int T, n;
        cin>>T;
        while(T--){
            scanf("%d",&n);
            for(int i = 0; i < n; ++i){
                cin>>x[i]>>y[i];
                ary[i]=Point(x[i],y[i]);
            }
            sort(x, x + n);
            sort(y, y + n);
            sx[0] = x[0];
            sy[0] = y[0];
            for(int i = 1; i < n; ++i){
                sx[i] = sx[i - 1] + x[i];
                sy[i] = sy[i - 1] + y[i];
            }
    
            ll ans=1,sumx,sumy;
            ans<<=60;
            for(int i=0;i<n;i++)
            {
                int rankx = lower_bound(x,x+n,ary[i].x)-x;//求出数组x中比ary[i].x小的数
                int ranky = lower_bound(y,y+n,ary[i].y)-y;
               
                sumx = ll(ary[i].x)*(rankx)-sx[rankx-1]+sx[n-1]-sx[rankx]-ll(ary[i].x)*(n-1-rankx);
                sumy = ll(ary[i].y)*(ranky)-sy[ranky-1]+sy[n-1]-sy[ranky]-ll(ary[i].y)*(n-1-ranky);
    
                ans=Min(ans,sumx+sumy);
            }
    
           cout<<ans<<endl;
    
    
    
        }
    }

    1004

      题意 :
        给出一个图,每一条边都有权值,给定k个点删除 k-1条边是 这 k个点不联通,
        求删除的边的和权值最小
    题解:
      kuskal 建生成树的过程,只不过将 边按从大到小牌,(因为 先将大边 插入到树中
      这样保证我们删边时 ,删的是最小的,(如果是按从小的大牌的话,我们选中的就是最大的 将两个要删的联通的边
       因为 我们这样,是先用的小边 建树)
      比赛是没想到,看到题解,擦涣然大悟 汗。。。。。。)
     
      没加入一条边时判断 是否将,俩个给定的点联通,如果是,则将这条边删除
     
     
      开始想到 判断是否将两个给定的点联通,难道要 遍历一下吗,那么大的数据两
     
      后来想到 ,我么可以将 给定的点作为 集合的表,这样就可以在 O(1)的时间内判断了

    View Cod
     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 #include<set>
     8 #include<map>
     9 #define Min(a,b)  a>b?b:a
    10 #define Max(a,b)  a>b?a:b
    11 #define CL(a,num)  memset(a,num,sizeof(a));
    12 #define maxn 200000
    13 using namespace std;
    14 struct node
    15 {
    16     int x;
    17     int y;
    18     int cost;
    19 }p[maxn];
    20 int f[maxn],vis[maxn];
    21 int find(int x)
    22 {
    23     if(f[x]!=x)f[x]=find(f[x]);
    24     return f[x];
    25 }
    26 int cmp( const void *a ,const void *b)
    27 {
    28    return (*(node *)a).cost < (*(node *)b).cost ? 1 : -1;
    29 }
    30 int main()
    31 {
    32     freopen("in.txt","r",stdin);
    33     int t,n,k,i,a;
    34     scanf("%d",&t);
    35     while(t--)
    36     {
    37         scanf("%d%d",&n,&k);
    38         for(i=0;i<=n;i++)f[i]=i;
    39         for(i=0;i<n-1;i++)
    40         {
    41             scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].cost);
    42 
    43         }
    44 
    45         CL(vis,0);
    46         for(i=0;i<k;i++)
    47         {
    48             scanf("%d",&a);
    49             vis[a]=1;
    50         }
    51         qsort(p,n-1,sizeof(p[0]),cmp);
    52         long long ans=0;
    53        for(i=0;i<n-1;i++)
    54        {
    55            int x=find(p[i].x);
    56            int y=find(p[i].y);
    57            if(vis[x]&&vis[y])ans+=p[i].cost;
    58            else
    59            {
    60 
    61                 if(vis[x])
    62                  f[y]=x;
    63                  else
    64                  if(vis[y])f[x]=y;
    65                  else f[x]=y;
    66 
    67            }
    68        }
    69        cout<<ans<<endl;
    70     }
    71 }
  • 相关阅读:
    SQL Serever学习16——索引,触发器,数据库维护
    微信WeUI基础
    SQL Serever学习15——进阶
    SQL Serever学习14——存储过程和触发器
    微信WeUI入门2
    微信WeUI入门
    数据库—索引
    数据库—四种存储引擎
    视图
    事务
  • 原文地址:https://www.cnblogs.com/acSzz/p/2610670.html
Copyright © 2020-2023  润新知