第三屆華中地區邀請賽網路賽題解

果7發表於2014-04-16

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;
}


相關文章