第三届华中地区邀请赛网络赛题解

Problem 1537 - A - Stones I

Time Limit: 1000MS   Memory Limit: 65536KB   
Total Submit: 491  Accepted: 90  Special Judge: No

Description

Xiaoming took the flight MH370 on March 8, 2014 to China to take the ACM contest in WHU. Unfortunately, when the airplane crossing the ocean, a beam of mystical light suddenly lit up the sky and all the passengers with the airplane were transferred to another desert planet.

 

When waking up, Xiaoming found himself lying on a planet with many precious stones. He found that:

 

There are n precious stones lying on the planet, each of them has 2 positive values ai and bi. Each time Xiaoming can take the ith of the stones ,after that, all of the stones’ aj (including the stones Xiaoming has taken) will cut down bi units.

 

Xiaoming could choose arbitrary number (zero is permitted) of the stones in any order. Thus, he wanted to maximize the sum of all the stones he has been chosen. Please help him.

Input

The input consists of one or more test cases.

First line of each test case consists of one integer n with 1 <= n <= 1000.
Then each of the following n lines contains two values ai and bi.( 1<= ai<=1000, 1<= bi<=1000)
Input is terminated by a value of zero (0) for n. 

Output

For each test case, output the maximum of the sum in one line.

Sample Input

1
100 100
3
2 1
3 1
4 1
0

Sample Output

0
3

Hint

Source

 

 

题目大意:有一堆石头,每个石头有aibi值,我们每拿起一个石头,所有的石头的ai值都会减去一个bi值,问你拿

石头使得sum最大,sum为所有的ai之和。是减去bi之后的。

 

解题思路:我们可以把问题简化,如果拿起n个石头,那么所有的ai都会减去b1+..+bn值,我们可以直接枚举n,再给

ai-n*bi排个序,选前n个即可,具体见代码。

 

题目地址:http://acm.whu.edu.cn/land/problem/detail?problem_id=1537

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

struct node
{
    int a;
    int b;
    int c;
}nod[1005];

int cmp(node p1,node p2)
{
    if(p1.c>=p2.c) return 1;
    return 0;
}

int main()
{
    int n,i,j;

    while(cin>>n&&n)
    {
        for(i=0;i<n;i++)
            scanf("%d%d",&nod[i].a,&nod[i].b);

        int ans=0;
        for(i=1;i<=n;i++)  //枚举拿起石头的个数
        {
            for(j=0;j<n;j++)
                nod[j].c=nod[j].a-nod[j].b*i;
            sort(nod,nod+n,cmp);

            int tmp=0;
            for(j=0;j<i;j++)
                tmp+=nod[j].c;
            ans=max(ans,tmp);
        }
        cout<<ans<<endl;
    }

    return 0;
}


 

Problem 1538 - B - Stones II

Time Limit: 1000MS   Memory Limit: 65536KB   
Total Submit: 365  Accepted: 49  Special Judge: No

Description

Xiaoming took the flight MH370 on March 8, 2014 to China to take the ACM contest in WHU. Unfortunately, when the airplane crossing the ocean, a beam of mystical light suddenly lit up the sky and all the passengers with the airplane were transferred to another desert planet.

 

When waking up, Xiaoming found himself lying on a planet with many precious stones. He found that:

 

There are n precious stones lying on the planet, each of them has 2 positive values ai and bi. Each time Xiaoming can take the ith of the stones ,after that, all of the stones’ aj (NOT including the stones Xiaoming has taken) will cut down bi units.

 

Xiaoming could choose arbitrary number (zero is permitted) of the stones in any order. Thus, he wanted to maximize the sum of all the stones he has been chosen. Please help him.

Input

The input consists of one or more test cases.

First line of each test case consists of one integer n with 1 <= n <= 1000.
Then each of the following n lines contains two values ai and bi.( 1<= ai<=1000, 1<= bi<=1000)
Input is terminated by a value of zero (0) for n. 

Output

For each test case, output the maximum of the sum in one line.

Sample Input

1
100 100
3
2 1
3 1
4 1
0

Sample Output

100
6

Hint

Source

 

 

题目大意:这题是上一题的升级版,不过区别是每次拿起石头的时候,没有被选到的石头都会减去拿起石头的bj值。

 

解题思路:动态规划题目。如果被选,bi小的肯定被先选。因为,如果某两块石头,bi大的先选了;那么交换

这两块石头的选取顺序,可以得到更大的价值。所以先对bi排个序,然后再dp.

dp[i][j]表示选第i个物品后还要选择j个物品,那么

dp[i][j]=max(dp[i-1][j],dp[i-1][j+1]+a[i]-b[i]*j)

                       不拿第i个         拿第i个            

 

题目地址:http://acm.whu.edu.cn/land/problem/detail?problem_id=1538

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1005;

struct node
{
    int a;
    int b;
}nod[maxn];

int cmp(node p1,node p2)
{
    if(p1.b<p2.b) return 1;
    else if(p1.b==p2.b&&p1.a<p2.a) return 1;
    return 0;
}

int dp[maxn][maxn];
//dp[i][j]表示选第i个物品后还要选择j个物品
//dp[i][j]=max(dp[i-1][j],dp[i-1][j+1]+a[i]-b[i]*j)
//              不拿第i个        拿第i个

int main()
{
    int n,i,j;

    while(cin>>n&&n)
    {
        for(i=1;i<=n;i++)
            scanf("%d%d",&nod[i].a,&nod[i].b);

        sort(nod+1,nod+n+1,cmp);
        memset(dp,0,sizeof(dp));

        for(i=1;i<=n;i++)
        {
            for(j=0;j<n;j++)
                dp[i][j]=max(dp[i-1][j],dp[i-1][j+1]+nod[i].a-nod[i].b*j);
        }
        cout<<dp[n][0]<<endl;
    }

    return 0;
}


 

Problem 1540 - D - Fibonacci

Time Limit: 1000MS   Memory Limit: 65536KB   
Total Submit: 279  Accepted: 49  Special Judge: No

Description

Calculate the sum of the cubes of the first n items in Fibonacci sequence in which the first two are both 1.

Input

The input consists of one or more test cases.

First line of each test case consists only one integer n. (1<=n<=10^9)

Input is terminated by a value of zero (0) for n.

Output

For each test case, output the answer mod 1000000007.

Sample Input

1
2
3

Sample Output

1
2
10

Hint

Source

 

 

题目大意:只要知道cube是三次方就可以了,fibo三次方的前n项和。

 

        解题思路:男神当时就很强的敏感到是矩阵的快速幂,但是当时没找出公式,大一的队伍竟然在网上找到了

公式。。。然后我就误以为是暴力,开始打表。


 

题目地址:http://acm.whu.edu.cn/land/problem/detail?problem_id=1540

 

AC代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#define ll long long
using namespace std;

const int mod = 1e9+7;
ll ans[5][5],bas[5][5],tmp[5][5];

void init()
{
    ans[0][0]=ans[0][1]=ans[0][2]=ans[1][1]=ans[1][2]=1;
    ans[2][1]=ans[3][1]=ans[3][4]=ans[4][1]=ans[4][3]=1;
    ans[1][0]=ans[2][0]=ans[3][0]=ans[4][0]=ans[2][2]=0;
    ans[3][2]=ans[4][2]=ans[2][3]=ans[2][4]=ans[4][4]=0;
    ans[0][3]=ans[0][4]=ans[1][3]=ans[1][4]=3;
    ans[3][3]=2;
    int i,j;
    for(i=0;i<5;i++)
        for(j=0;j<5;j++)
        {
            bas[i][j]=ans[i][j];
        }
}

void cal1()   //n>>=1
{
    int i,j,k;
    for(i=0;i<5;i++)
    {
        for(j=0;j<5;j++)
        {
            tmp[i][j]=bas[i][j];
            bas[i][j]=0;
        }
    }

    for(i=0;i<5;i++)
    {
        for(j=0;j<5;j++)
        {
            for(k=0;k<5;k++)
            {
                bas[i][j]=(bas[i][j]+tmp[i][k]*tmp[k][j])%mod;
            }
        }
    }
}

void cal2()   //n&1
{
    int i,j,k;
    for(i=0;i<5;i++)
    {
        for(j=0;j<5;j++)
        {
            tmp[i][j]=ans[i][j];
            ans[i][j]=0;
        }
    }

    for(i=0;i<5;i++)
    {
        for(j=0;j<5;j++)
        {
            for(k=0;k<5;k++)
            {
                ans[i][j]=(ans[i][j]+tmp[i][k]*bas[k][j])%mod;
            }
        }
    }
}

int main()
{
    int n,i;
    while(cin>>n&&n)
    {
        if(n==1)      {  puts("1"); continue;}
        else if(n==2) {  puts("2"); continue;}
        n-=3;
        init();
        while(n)
        {
            if(n&1) cal2();
            cal1();
            n>>=1;
        }

        ll res;
        res=2*ans[0][0];
        for(i=1;i<5;i++)
            res+=ans[0][i];
        res=(res+mod)%mod;
        cout<<res<<endl;
    }
    return 0;
}


 

Problem 1542 - F - Countries

Time Limit: 1000MS   Memory Limit: 65536KB   
Total Submit: 325  Accepted: 52  Special Judge: No

Description

 There are n countries at planet X on which Xiao Ming was born.

 

Some countries, which have been sharing fine bilateral relations, form a coalition and thus all of their citizens will benefit from a policy for which all the travels between these countries will become totally free.

 

But it is not easy to travel between countries distributed in different coalitions. If possible, it must cost some money called YZB(yu zhou bi) which is always positive.

 

Help Xiao Ming determine the minimum cost between countries.

Input

The input consists of one or more test cases.

First line of each test case consists two integers n and m. (1<=n<=10^5, 1<=m<=10^5)

Each of the following m lines contains: x y c, and c indicating the YZB traveling from x to y or from y to x. If it equals to zero, that means x and y are in the same coalition. (1<=x, y<=n, 0<=c<=10^9)
You can assume that there are no more than one road between two countries.

Then the next line contains an integer q, the number of queries.(1<=q<=200)

Each of the following q lines contains: x y. (1<=x, y<=n)

It is guaranteed that there are no more 200 coalitions.

Input is terminated by a value of zero (0) for n.

Output

For each test case, output each query in a line. If it is impossible, output -1.

Sample Input

6 5
1 2 0
2 4 1
3 5 0
1 4 1
1 6 2
3
4 2
1 3
4 6
0

Sample Output

1
-1
3

Hint

Source

 

题目大意:题目说有n最大为10^5个点,问你两点之间的最短距离,不过如果两点之间距离为0,那么他们就是

一个国家,最多有200个国家。

 

解题思路:题目到这里就很清楚了,先使用并查集,然后在离散把所有的点一一对应到mp里面去,mp里面最

多有200个点,然后再重新建立边,然后使用floyd,就ok了。

 

题目地址:http://acm.whu.edu.cn/land/problem/detail?problem_id=1545

 

AC代码:

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 100005;
const int INF = 1e9+7;

int mp[maxn];  //映射表
int fa[maxn];
int dis[205][205];
int u[maxn],v[maxn],w[maxn];

void init()
{
    int i,j;
    for(i=1;i<maxn;i++)
        fa[i]=i;
    for(i=1;i<205;i++)
    {
        for(j=1;j<205;j++)
        {
            if(i==j) dis[i][j]=0;
            else dis[i][j]=INF;
        }
    }
}

int find1(int x)  //路径压缩的find1
{
    if(fa[x]!=x)  fa[x]=find1(fa[x]);
    return fa[x];
}

void merge1(int x,int y)
{
    x=find1(x);
    y=find1(y);
    fa[x]=y;
}

void floyd(int n)
{
    int i,j,k;
    for(k=1;k<n;k++)
    {
        for(i=1;i<n;i++)
        {
            for(j=1;j<n;j++)
            {
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
            }
        }
    }
}

int main()
{
    int n,m,q;
    int i;
    while(scanf("%d",&n)&&n)
    {
        scanf("%d",&m);
        init();

        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u[i],&v[i],&w[i]);
            if(w[i]==0) merge1(u[i],v[i]);
        }

        int t=1;
        for(i=1; i<=n; i++)   //统一标号,离散
            if(fa[i] == i)
            {
                mp[i] = t++;
            }

        for(i=1; i<=n; i++)
        {
            if(fa[i]!=i)
            {
                int tmp=find1(i);
                mp[i]=mp[tmp];   //一一映射到标号
            }
        }

        //cout<<mp[1]<<" "<<mp[2]<<" "<<mp[4]<<endl;

        //重新建图,给边赋值
        for(i=1;i<=m;i++)
        {
            int x,y;
            x=find1(u[i]),y=find1(v[i]);
            if(x!=y)
            {
                x=mp[x],y=mp[y];
                dis[x][y]=min(dis[x][y],w[i]);
                dis[y][x]=dis[x][y];
            }
        }

        floyd(t);
        scanf("%d",&q);
        while(q--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            x=mp[x],y=mp[y];

            //cout<<x<<" "<<y<<endl;
            if(dis[x][y]==maxn) puts("-1");
            else printf("%d\n",dis[x][y]);
        }
    }
    return 0;
}


 

Problem 1545 - I - Twenty-four

Time Limit: 1000MS   Memory Limit: 65536KB   
Total Submit: 502  Accepted: 109  Special Judge: No

Description

There are 8 cards :1 1 2 2 3 3 4 4, you need to find out how many ways are there to choose 4 cards and these 4 cards can be used to play the game twenty-four. Attention, there is no difference between cards with the same number, 1 2 2 3 and 1’ 2 2 3 will be regarded as one solution, etc.

 

Hint: twenty-four is a game in which you are given 4 cards marked with numbers, and you may use +, -, * to connect all the four cards and make the result to be 24.

Input

No input in this problem.

Output

Output the result in one line. 

Sample Input

Sample Output

Its what you need to output. :)

Hint

Source

 

题目大意:题目说的意思是使用+,-,*使得从11223344这八个数里面选四个数使得答案为2484

的方案数,当时我把题目理解错了,觉得使用这个就不能使用括号。题目理解错全错。。。实际上直接组合就好。要不是

YYD,估计后面几个小时我全在写这个题目了。。

有人直接从1开始枚举着往上交。

 

解题思路:直接dfs把。。

 

题目地址:http://acm.whu.edu.cn/land/problem/detail?problem_id=1545

 

AC代码:  ---代码有点搓。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

int a[8]={1,1,2,2,3,3,4,4};
int visi[8];
int b[2005];   //把8个数的排列全部枚举出来压缩保存到b中
int c[4];
int d[4];
int t;
int mp[5005];  //可以的状态按大小排序只要一个

void dfs1(int x)
{
    if(x>1000)
    {
        b[t++]=x;
        return;
    }
    for(int i=0;i<8;i++)
    {
        if(!visi[i])
        {
            visi[i]=1;
            dfs1(x*10+a[i]);
            visi[i]=0;
        }
    }
}

void dfs2(int cur,int ste)
{
    if(ste==4&&cur==24)
    {
        for(int i=0;i<4;i++)
            d[i]=c[i];
        sort(d,d+4);
        int tmp=0;
        for(int i=0;i<4;i++)
            tmp=tmp*10+d[i];
        mp[tmp]=1;
        return;
    }
    else if(ste==4) return;
    dfs2(cur+c[ste],ste+1);
    dfs2(cur-c[ste],ste+1);
    dfs2(cur*c[ste],ste+1);
}

int main()
{
    int i,j;
    t=0;
    memset(visi,0,sizeof(visi));
    memset(mp,0,sizeof(mp));
    dfs1(0);

    for(i=0;i<t;i++)
    {
        int tmp=b[i];
        for(j=0;j<4;j++)
        {
            c[j]=tmp%10;
            tmp/=10;
        }
        dfs2(c[0],1);
    }


    int ans=0;
    for(i=0;i<5000;i++)
    {
        if(mp[i])
            ans++;
    }
    cout<<ans<<endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值