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 }
原文地址:https://www.cnblogs.com/acSzz/p/2610670.html