**Codeforces Round #250 (Div. 2) C. The Child and Toy ACM解题报告(贪心难题)

快哭了今天是惨遭吊打,和学长做去年的儿童节专场,只做出来A题,B题直接暴力以为会超时,dp了半天过不了,C题贪心贪错了。。。

这题的大意是有n个部件,要把他们全部破坏,破坏i就需要与i相连的那些部件的能量,比如j,k与i相连,破坏i就需要vj+vk的能量,求全部破坏需要多少能量。

我也是太年轻,直接按照每个部件拆除所需能量升序排序,然后拆能量需要最小的。

这个方法的错误在于,也许有几次拆的时候,消耗了最大的那部分能量,所以不是最优解。

贪心的思路是先拆该点能量最大的,而不是所需能量最小的,这样先把该点能量最大的拆了,后面的部件拆的时候就不会计算到最大的这个能量。(有点绕,但是想想就可以明白)

#include<iostream>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<stack>
using namespace std;
#define MAX 105
typedef long long LL;
const double pi=3.141592653589793;
const int INF=1e9;
const double inf=1e20;
int edge[1005][1005];
struct vex
{
    int w,num,degree;
    vex(int degree=0): degree(degree) {}
} p[1005];
bool cmp(struct vex a,struct vex b)
{
    return a.w>b.w;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    memset(edge,0,sizeof(edge));
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&p[i].w);
        p[i].num=i;
    }
    for(int i=0; i<m; i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        p[x].degree+=p[y].w;
        p[y].degree+=p[x].w;
        edge[x][y]=edge[y][x]=1;
    }
    sort(p+1,p+n+1,cmp);
    int sum=0;
    for(int i=1; i<=n; i++)
    {
        sum+=p[i].degree;
        int r=p[i].num;
        for(int j=i+1; j<=n; j++)
        {
            int s=p[j].num;
            if(edge[r][s]||edge[s][r])
            {
                p[j].degree-=p[i].w;
            }
        }
    }
    printf("%d\n",sum);
    return 0;
}


你可能感兴趣的:(ACM,codeforces)