华东交通大学2014年ACM“双基”程序设计竞赛解题报告

来源:互联网 发布:淘宝犯法 编辑:程序博客网 时间:2024/04/27 19:55

1001         KK的GFriend

本题水题。遍历输入数据给出的字符串。如果出现的I LOVE U各个字符都至少都有m个的话,则满足要求,否则不满足。

之前比赛时,输出描述的字符串和Sample Output不符(Sample Output为正确答案),导致部分同学wrong answer,请见谅。

#include<iostream>#include<cstring>#include<string>#include<cstdio>using namespace std;const int maxn=10001;char inp[maxn];int num[6];int main(){    int cas,n,m;    scanf("%d",&cas);    while(cas--)    {        memset(num,0,sizeof(num));        scanf("%d%d",&n,&m);        for(int i=1; i<=n; i++)        {            scanf("%s",&inp);            for(int i=0; i<strlen(inp); i++)            {                switch(inp[i])                {                    case 'I':num[0]++;break;                    case 'L':num[1]++;break;                    case 'O':num[2]++;break;                    case 'V':num[3]++;break;                    case 'E':num[4]++;break;                    case 'U':num[5]++;break;                }            }        }        int res=maxn;        for(int i=0; i<6; i++)            res=min(res,num[i]);        if(res>=m) printf("KK will have a girlfriend!\n");        else  printf("KK can only have gay friend~\n");    }    return 0;}



1002         炮打学弟

这题是一道简单题,主要是要考虑的情况稍多,如果都考虑到了就没有什么了。

需要注意的地方:

1. x2<x1 输出 Xue di so diao can fly

2. x2=x1时

(1)y=0 输出0.00

(2)y!=0&&vx>0 输出 Xue di so diao can fly

3. x2>x1&&vx=0输出 Xue di so diao can fly

其他情况常规的算一下就可以了。

标准程序:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<set>#include<vector>#include<queue>#include<map>#include<algorithm>#include<cmath>#include<stdlib.h>#include<time.h>using namespace std;#define mmax 100000+100int main(){    int x1,x2,y,vx;    double vy,g=9.8;    int t;    cin>>t;    //freopen("I:\\input.txt","r",stdin);    //freopen("I:\\ouput.txt","w",stdout);    while(t--){        cin>>x1>>x2>>y>>vx;        if(x1>x2){            cout<<"Xue di so diao can fly"<<endl;            continue;        }        if(x1==x2){            if(y==0){                printf("%.2f\n",0.00);                continue;            }            else if(vx>0)  cout<<"Xue di so diao can fly"<<endl;            else{                double t=sqrt(2*y/g);                printf("%.2f\n",g*t);            }            continue;        }        else{            if(vx==0){                cout<<"Xue di so diao can fly"<<endl;                continue;            }            else{                double t=(x2-x1)*1.0/vx;                vy=(0.5*g*t*t+y)/t;                printf("%.2f\n",vy);            }        }    }}


1003         区间平均值

这题是水题,直接暴力求平均值即可。

 

1004         饿了么

这题是水题,直接排个序就好了,1000的数据量,用冒泡排序都可以。

 

1005         分辨机器人

m<=15  2^15==32768 所以可以直接暴力解决。但是由于开始数据出问题了,导致很多同学wa了,实在抱歉,想知道自己算法是否OK的同学可以到赛后(http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1005&cid=25698&problem=Problem%20%20E)提交。

标准程序:

#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio>#include <queue>#include <cmath>#include <vector>#include <set>#include <bitset>#include <map>#define  pb push_back#define  lson l,m,rt<<1#define  rson m+1,r,rt<<1|1typedef  long long LL;using namespace std;int s[105][20];int T,n,m,ans;int B[20];string ko;map<string,int>M;void dfs(int *B,int num){    if(num==m)    {        M.clear();        for(int i=1;i<=n;i++)        {            ko = "";            for(int j=1;j<=m;j++)                if(B[j]==1) ko += (s[i][j]+'0');            if(M[ko]) return ;            else M[ko] = 1;        }        int flag = 0;        for(int i=1;i<=m;i++) flag+=B[i];        if(ans>flag)            ans = flag;    }    else    {        B[num+1] = 0;        dfs(B,num+1);        B[num+1] = 1;        dfs(B,num+1);    }}void solve(){    ans = m;    B[0] = 0;    dfs(B,0);    printf("%d\n",ans);}int main(){    scanf("%d",&T);    while(T--)    {        memset(B,0,sizeof(B));        scanf("%d%d",&n,&m);        for(int i=1; i<=n; i++)            for(int j=1; j<=m; j++)            {                scanf("%d",&s[i][j]);            }        solve();    }    return 0;}


1006         佳米的问题

这是一个想法题,首先我们需要找出最大的LCM(x,y).由于x+y==m&& x>=1 && y>=1 ,有一个很简单的数学依据,加入我们只是找(x*y)最大,那肯定( m/2*(m-m/2) )最大,因为这就是一个开口向下的二次函数曲线,而顶点就是(m/2)或者(m-m/2),但是我们要找的是x与y的最小公倍数,所以只需要从m/2开始向下枚举x,找到gcd(x,m-x)==1,此时LCM(x,y)最大。

然后就是如何用LCM(x,y)去填充数组使得最小的元素最大的问题了,那么这个其实有一个很简单的方法,直接二分答案即可。

标准程序:

#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio>#include <queue>#include <cmath>#include <vector>#include <set>#include <bitset>#include <map>#define  pb push_back#define  lson l,m,rt<<1#define  rson m+1,r,rt<<1|1typedef  long long LL;using namespace std;LL gcd(LL a,LL b){    return a==0?b:gcd(b%a,a);}const int maxn = 100010;LL s[maxn];LL T,n,num,m;bool solve(LL mid,LL num){    LL ok = num;    for(int i=1;i<=n;i++)    {        if(s[i] < mid){            ok -= abs( mid - s[i] );        }        if(ok<0) break;    }    return ok>=0;}int main(){    #ifndef ONLINE_JUDGE      freopen("in.txt","r",stdin);      freopen("out2.txt","w",stdout);    #endif ///ONLINE_JUDGE    scanf("%I64d",&T);    while(T--){        scanf("%I64d",&n);        for(int i=1;i<=n;i++)        {            scanf("%I64d",&s[i]);        }        scanf("%I64d",&m);        for(LL i=m/2;i>=1;i--)        {            if(gcd(i,m-i)==1)            {                num=i*(m-i);                break;            }        }        LL l=-1*1e9,r = 1ll*1e16,mid,ans=-1*1e9;        while(l<=r)        {            mid = (l+r)/2;            if(solve(mid,num)){                ans = max(ans,mid);                l = mid + 1;            }            else r = mid - 1;        }        printf("%I64d\n",ans);    }    return 0;}


1007         Crisis

图论。本题可谓是排在难题位置的简单题。描述偏多,但是只要学习过最大流算法的同学应该都可以做出来。

N件武器,每件都可以选择特定的几个目标进行攻击。但是每件武器只允许攻击一次并只能造成1点伤害。因此,我们构建网络,将n件武器每件当作一个点,与源点相连,形成的边容量为1。再将m个目标当作n个点,若某一武器能够攻击到敌人,则将它们两个点相连,边容量为1。

又由于每个敌人的护盾有限。而被摧毁的战舰无法再被攻击,因此,将m个敌人分别与汇点相连,边容量为该敌人的护盾值。

至此,建模完毕。接下来只需要套用最大流算法,即可计算出最大攻击输出。

标准程序:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<queue>#define INF 0x7fffffffusing namespace std;const int maxn=1010;class Edge{public :    int from,to,cap,flow;    Edge(int fr,int t,int c,int fl)    {        from=fr;        to=t;        cap=c;        flow=fl;    };};class Dinic{private:    int s,t,c,m,n;    vector<Edge>edges;    vector<int>G[maxn];    bool vis[maxn];    int dist[maxn];    int cur[maxn];public:    void AddEdge(int from,int to,int cap)    {        Edge e(from,to,cap,0);        edges.push_back(e);        e.from=to;        e.to=from;        e.cap=0;        edges.push_back(e);        c=edges.size();        G[from].push_back(c-2);        G[to].push_back(c-1);    }    bool BFS()    {        queue<int>Q;        memset(vis,0,sizeof(vis));        Q.push(s);        dist[s]=0;        vis[s]=1;        while(!Q.empty())        {            int x=Q.front();            Q.pop();            for(int i=0; i<G[x].size(); i++)            {                Edge& e=edges[G[x][i]];                if(!vis[e.to]&&e.cap>e.flow)                {                    vis[e.to]=1;                    dist[e.to]=dist[x]+1;                    Q.push(e.to);                }            }        }        return vis[t];    }    int DFS(int x,int a)    {        if(x==t||a==0)return a;        int flow=0,f;        for(int& i=cur[x]; i<G[x].size(); i++)        {            Edge& e=edges[G[x][i]];            if(dist[x]+1==dist[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0)            {                e.flow+=f;                edges[G[x][i]^1].flow-=f;                flow+=f;                a-=f;                if(a==0)break;            }        }        return flow;    }    int Maxflow(int s,int t)    {        this->s=s;        this->t=t;        int flow=0;        while(BFS())        {            memset(cur,0,sizeof(cur));            flow+=DFS(s,INF);        }        return flow;    }    void init()    {        edges.clear();        for(int i=0; i<maxn; i++)        {            G[i].clear();            dist[i]=0;        }    }} Do;int main(){    int n,m,k,hp,t;    cin>>t;    while(t--)    {        cin>>n>>m;        Do.init();        for(int i=1; i<=n; i++)        {            Do.AddEdge(0,i,1);            cin>>k;            int tar;            for(int j=1; j<=k; j++)            {                cin>>tar;                Do.AddEdge(i,n+tar,1);            }        }        for(int i=1; i<=m; i++)        {            cin>>hp;            Do.AddEdge(n+i,n+m+1,hp);        }        cout<<Do.Maxflow(0,n+m+1)<<endl;    }    return 0;}



1008         KiKi的难题

这题是一个简单的三维的dp。

Intdp[110][110][110];

dp[i][j][k] 表示第i个岛屿到第j个岛屿没有挖且使用魔法棒剩余次数为k 所能获得大最大价值

for(int i=n-1; i>=1; i--)//枚举剩余岛屿的个数for(int j=1;j+i-1<=n; j++)//枚举最左边的岛屿位置for(int k=0; k<=m; k++)//枚举魔法棒可使用的次数{        int add=j+i-1;        if(j!=1)           {                    dp[j][add][k]=max(dp[j][add][k],dp[j-1][add][k]+p[j-1]);                    dp[j][add][k]=max(dp[j][add][k],dp[j-1][add][k+1]+(m-k)*p[j-1]);           }           if(add!=n)           {                    dp[j][add][k]=max(dp[j][add][k],dp[j][add+1][k]+p[add+1]);                    dp[j][add][k]=max(dp[j][add][k],dp[j][add+1][k+1]+(m-k)*p[add+1]);           }}

最后输出最大值就可以了。

标准程序:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<vector>#include<cstdlib>#include<stack>#include<queue>#include<map>#include<algorithm>using namespace std;int dp[110][110][110];int main(){    int t;cin>>t;    int n,m,p[110];    while(t--){        cin>>n>>m;        for(int i=1;i<=n;i++) cin>>p[i];        memset(dp,0,sizeof(dp));        for(int i=n-1; i>=1; i--)        {            for(int j=1; j+i-1<=n; j++)                for(int k=0; k<=m; k++)                {                    int add=j+i-1;                    if(j!=1)                    {                        dp[j][add][k]=max(dp[j][add][k],dp[j-1][add][k]+p[j-1]);                        dp[j][add][k]=max(dp[j][add][k],dp[j-1][add][k+1]+(m-k)*p[j-1]);                    }                    if(add!=n)                    {                        dp[j][add][k]=max(dp[j][add][k],dp[j][add+1][k]+p[add+1]);                        dp[j][add][k]=max(dp[j][add][k],dp[j][add+1][k+1]+(m-k)*p[add+1]);                    }                }        }        int mmax=0;        if(m==0) cout<<dp[1][1][0]+p[1]<<endl;        else{             for(int i=1;i<=n;i++) mmax=max(mmax,dp[i][i][1]+p[i]*m);             cout<<mmax<<endl;        }    }    return 0;}

以上即是本次比赛的全部解题报告以及部分标准程序代码,感谢大家对我校比赛的支持!

0 0
原创粉丝点击