沈阳化工大学第五届ACM校赛

Problem A: M1crosoft Exce1


直接的模拟题,代码:

#include
using namespace std;

struct stu
{
    string text;
    int align;
    struct stu *f;
  
} p[30][30],*self;
int main()
{
    //freopen("in.txt", "r", stdin);
    int t,n,m,d,k,i,j,flag,b,y;
    char s[10],ch[300];
    char a,x;
    cin>>t;
    while(t--)
    {
        for(i=0; i<30; i++)
        {
            for(j=0; j<30; j++)
            {
                p[i][j].text="";
  
                p[i][j].f=&p[i][j];
                p[i][j].align=0;
  
            }
        }
        cin>>n>>m>>d>>k;
        while(k--)
        {
            scanf("%s",s);
            getchar();
            if(strcmp(s,"text")==0)
            {
                scanf("%c%d ",&a,&b);
                fgets(ch,300,stdin);
                ch[strlen(ch)-1]='\0';
                p[a-'A'+1][b].text=ch;
            }
            else if(strcmp(s,"align")==0)
            {
                scanf("%c%d%s",&a,&b,ch);
                if(strcmp(ch,"left")==0)
                {
                    p[a-'A'+1][b].align=0;
                }
                else if(strcmp(ch,"right")==0)
                {
                    p[a-'A'+1][b].align=1;
                }
            }
            else if(strcmp(s,"merge")==0)
            {
                scanf("%c%d %c%d",&a,&b,&x,&y);
                for(i=a; i<=x; i++)
                {
                    for(j=b; j<=y; j++)
                    {
                        p[i-'A'+1][j].f=&p[x-'A'+1][y];
                    }
                }
            }
        }
        for(i=-m-1; itext.length()align==1)
                    {
                        for(k=d-self->text.length(); k>0; k--)
                        {
                            cout<<" ";
                        }
                        cout<text;
                    }
                    else if(self->align==0)
                    {
                        cout<text;
  
                        for(k=d-self->text.length(); k>0; k--)
                        {
                            cout<<" ";
                        }
                    }
                    self->text="";
                }
                else
                {
                    if(self==&p[i][j])
                    {
                        flag=1;
                    }
                    cout<text.substr(0,d);
                    self->text=self->text.substr(d);
                }
                if(j==m||p[i][j].f!=p[i][j+1].f)
                {
                    cout<<"|";
                }
                else
                {
                    if(self->text.length()==0)
                    {
                        cout<<" ";
                    }
                    else
                    {
                        cout<text.substr(0,1);
                        self->text=self->text.substr(1);
                    }
                }
            }
            cout<text.length()align==1)
                            {
                                for(k=d-self->text.length(); k>0; k--)
                                {
                                    cout<<" ";
                                }
                                cout<text;
                            }
                            else if(self->align==0)
                            {
                                cout<text;
                                for(k=d-self->text.length(); k>0; k--)
                                {
                                    cout<<" ";
                                }
                            }
                            self->text="";
                        }
                        else
                        {
                            cout<text.substr(0,d);
                            self->text=self->text.substr(d);
                        }
                    }
                    if(i==n||p[i][j].f!=p[i+1][j].f||p[i][j].f!=p[i][j+1].f)
                    {
                        cout<<"-";
                    }
                    else
                    {
                        self=p[i][j].f;
                        if(self->text.length()==0)
                        {
                            cout<<" ";
                        }
                        else
                        {
                            cout<text.substr(0,1);
                            self->text=self->text.substr(1);
                        }
                    }
                }
                cout<

Problem B: J VS B

题解:简单的博弈题,考虑k>1时一定是yes;k=1时判断n的奇偶

代码:

#include
using namespace std;
  
int main()
{
    //freopen("test01.in","r",stdin);
    //freopen("test01.out","w",stdout);
    int n,k;
    int T;
    while(scanf("%d",&T)!=EOF){
        while(T--){
            scanf("%d%d",&n,&k);
            if(k>1)
                printf("yes\n");
            else{
                if(n%2==0)
                    printf("no\n");
                else
                    printf("yes\n");
            }
        }
    }
    return 0;
}

Problem C: Jinixin Speech

题解:给你n个数,m次询问,每次询问是这样的:

输入 x,将会构造出一个新的序列,这个新的序列b[i]=a[x]-a[i](iSum2输出Keep dis

如果sum1=sum2输出Next time

如果Sum1j的时候

Sum2+=a[x][j]*(j-s[x]) (s[x]
然后扫一遍10个数就好了~


代码:

#include

using namespace std;
 
long long a[100005][11];
int main()
{
    long long i,j,n,m,x,tmp,A,B;
    string s;
    while(~scanf("%lld%lld",&n,&m))
    {
        memset(a,0,sizeof(a));
        cin>>s;
        for(i=0;itmp)  
                    B+=(i-tmp)*a[x-1][i];
            }
            if(A==B)
                printf("Next time\n");
            else if(A>B)
                printf("Keep some distance from me\n");
            else
                printf("I agree\n");
        }
    }
    return 0;
}

Problem D: Group Sum

题解:

题意:
给定一个数M,从1~9这9个数中选出M个不同的数,组成一个集合。
当集合中所有元素之和等于N时,输出该集合,要求找到所有满足条件的集合。
注:集合之间从小到大排序,集合内元素也要从小到大排序。


想法:
拿到题,因为集合中的元素来自1~9,且要求有序输出,所以很容易想到用循环嵌套来做,但因为题中M不确定,故用M个循环解决本题可能比较麻烦。循环与递归在某种程度上是可以相互转换的,故我们通过递归来思考本题。

vector minums;
void dfs(int i,int m)
{
    if(m==(int)minums.size())
    {
        //找到了一个长度为m的集合
        return;
    }
    for(i++;i<=9;i++)
    {
        minums.push_back(i);//将i加入minums集合末尾
        dfs(i,m);
        minums.pop_back();//将minums集合末尾的元素删除
    }
}
调用:dfs(0,m);

通过上述代码可以找到所有长度为m的集合。
minums集合中的元素满足从小到大的顺序,且找到的长度为m的集合的先后顺序也满足从小到大。
下面我们只要着手判断该集合内所有元素之和是否等于n?如果等于n则把该集合再存储进一个大集合即可。


vector minums;
vector> nums;//大集合
void dfs(int i,int m,int n)
{
    if(n<0)//集合中元素之和已经超过n
    {
        return;//返回
    }
    if(m==(int)minums.size())//找到了一个长度为m的集合
    {
        if(n==0)//如果集合中所有元素之和等于n,则该集合minums符合要求
        {
            nums.push_back(minums);//将minums存储到集合nums中
        }
        return;//返回
    }
    for(i++;i<=9;i++)
    {
        minums.push_back(i);//将i加入minums集合末尾
        dfs(i,m,n-i);
        minums.pop_back();//将minums集合末尾的元素删除
    }
}
调用:dfs(0,m,n);

nums集合即为最终答案。



代码:

#include
#include
using namespace std;
vector minums;
vector> nums;
void dfs(int i,int k,int n)
{
    if(n<0)
    {
        return;
    }
    if(k==(int)minums.size())
    {
        if(n==0)
        {
            nums.push_back(minums);
        }
        return;
    }
    for(i++;i<=9;i++)
    {
        minums.push_back(i);
        dfs(i,k,n-i);
        minums.pop_back();
    }
}
int main()
{
    int k,n,i,j;
    while(~scanf("%d%d",&k,&n))
    {
        nums.clear();
        minums.clear();
        dfs(0,k,n);
        cout<<"[";
        for(i=0;i<(int)nums.size();i++)
        {
            cout<<"[";
            for(j=0;j


Problem E: Binary Tree

题意:
按层序给你一棵二叉树各节点值的序列(空节点值为null),要求建立该二叉树,并判断该二叉树是否具有对称性。
如果具有对称性,输出1。
如果不具有对称性,输出0,并输出该二叉树的先序遍历序列。
想法:
本题是模拟题,涉及“字符串处理”,“二叉树建树”,“先序遍历”。
注1:给定的序列是“A B C D ”这样的形式,字母表示节点的值,节点值后面一定有一个空格。
注2:题中说明“节点值为整数”,但大家需要考虑到负整数的情况!


****************************************************************************************************
//数据结构定义
struct TreeNode {
       int val;
       TreeNode *left,*right;
};
****************************************************************************************************
//将读入的序列转换为二叉树
TreeNode* deserialize(string data) 
{
	TreeNode *root,*head,*pre;
	queue p;
	int i=0,j=0,flag=1;//flag为0表示节点为空;为1表示正数;为-1表示负数。
	//由于需要知道所建树的根节点地址,故单独先读第一个数!
	while(data[i]!=' '&&ival=j*flag;//flag表示正负!
		head->left=head->right=NULL;
		p.push(head);//压入队列
	}
	while(!p.empty())
	{
		pre=p.front();//从队列中读出一个节点作为根节点
		p.pop();
		j=0;flag=1;i++;
		while(data[i]!=' '&&ileft=NULL;
		}
		else if(ival=j*flag;
			root->left=root->right=NULL;
			pre->left=root;//根的左孩子即为该数所在节点
			p.push(root);//将该数所在节点压入队列
		}
		j=0;flag=1;i++;
		while(data[i]!=' '&&iright=NULL;
		}
		else if(ival=j*flag;
			root->left=root->right=NULL;
			pre->right=root;//根的右孩子即为该数所在节点
			p.push(root);//将该数所在节点压入队列
		}
	}
	return head;//返回所建树根节点的地址
}
调用:deserialize(传入序列); 
****************************************************************************************************
//判断序列是否具有对称性
bool flag;
void dfs(struct TreeNode *Tleft,struct TreeNode *Tright)
{
    if(!flag)
    {
        return;
    }
    if(Tleft->val!=Tright->val)//左子树和右子树根节点值不相等,不对称!
    {
        flag=false;
        return;
    }
    if(Tleft->right&&Tright->left)//“左子树的右子树”和“右子树的左子树”都存在
    {
        dfs(Tleft->right,Tright->left);//递归,进一步判断“左子树的右子树和右子树的左子树”
    }
    else if(!Tleft->right&&!Tright->left)//“左子树的右子树”和“右子树的左子树”都不存在,对称
    {
        ;
    }
    else//“左子树的右子树”或“右子树的左子树”不存在,不对称!
    {
        flag=false;
        return;
    }
    if(Tleft->left&&Tright->right)//同理判断“左子树的左子树和右子树的右子树”
    {
        dfs(Tleft->left,Tright->right);
    }
    else if(!Tleft->left&&!Tright->right)
    {
        ;
    }
    else
    {
        flag=false;
        return;
    }
}
bool isSymmetric(struct TreeNode* root)
{
    flag=true;
    if(root)
    {
        if(root->right&&root->left)//树的根节点有左子树和右子树
        {
            dfs(root->left,root->right);//进一步判断树的左右子树情况
        }
        else if(!root->right&&!root->left)//树的根节点没有左子树和右子树,对称
        {
            ;
        }
        else//树的根节点没有左子树或右子树,一定不对称!
        {
            flag=false;
        }
    }
    return flag;
}
调用:isSymmetric(传入二叉树根节点地址);
****************************************************************************************************
//先序遍历二叉树
void tlr(struct TreeNode* root)
{
    if(root)
    {
	//操作root->val的语句写在这里,本题为“cout<val;”
	tlr(root->left);
	tlr(root->right);
    }
}
调用:tlr(传入二叉树根节点地址);


代码:

#include
#include
#include
using namespace std;
struct TreeNode {
    int val;
    struct TreeNode *left,*right;
};
int flag;
TreeNode* init(string data)
{
    TreeNode *root,*head,*pre;
    queue p;
    int i=0,j=0,flak=1;
    while(data[i]!=' '&&ival=j*flak;
        head->left=head->right=NULL;
        p.push(head);
    }
    while(!p.empty())
    {
        pre=p.front();
        p.pop();
        j=0;flak=1;i++;
        while(data[i]!=' '&&ileft=NULL;
        }
        else if(ival=j*flak;
            root->left=root->right=NULL;
            pre->left=root;
            p.push(root);
        }
        j=0;flak=1;i++;
        while(data[i]!=' '&&iright=NULL;
        }
        else if(ival=j*flak;
            root->left=root->right=NULL;
            pre->right=root;
            p.push(root);
        }
    }
    return head;
}
void dfs(struct TreeNode *Tleft,struct TreeNode *Tright)
{
    if(!flag)
    {
        return;
    }
    if(Tleft->val!=Tright->val)
    {
        flag=false;
        return;
    }
    if(Tleft->right&&Tright->left)
    {
        dfs(Tleft->right,Tright->left);
    }
    else if(!Tleft->right&&!Tright->left)
    {
        ;
    }
    else
    {
        flag=false;
        return;
    }
    if(Tleft->left&&Tright->right)
    {
        dfs(Tleft->left,Tright->right);
    }
    else if(!Tleft->left&&!Tright->right)
    {
        ;
    }
    else
    {
        flag=false;
        return;
    }
}
int isSymmetric(struct TreeNode* root) {
    flag=1;
    if(root)
    {
        if(root->right&&root->left)
        {
            dfs(root->left,root->right);
        }
        else if(!root->right&&!root->left)
        {
            ;
        }
        else
        {
            flag=0;
        }
    }
    return flag;
}
void tlr(struct TreeNode *root)
{
    if(!root)
    {
        return;
    }
    cout<val;
    tlr(root->left);
    tlr(root->right);
}
int main()
{
    string s;
    int num;
    struct TreeNode *lead;
    while(getline(cin,s))
    {
        lead=init(s);
        num=isSymmetric(lead);
        cout<

Problem F: The Clock of Station

题解:简单题

代码:

#include
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
    int x,y,z;
    scanf("%d%d%d",&x,&y,&z);
    printf("%d\n",(x+y)*z);
    }
    return 0;
}


Problem G: Count beans will be crazy

题解:(这是一个小学奥数改编的题目)由题意可得本题即求最小公倍数,需考虑到long long,还有直接打出来也是可以的

代码:

#include
long long gcd(long long n,long long m)
{
    long long a=n,b=m,r=a%b;
    while(r)
    {
        a=b;
        b=r;
        r=a%b;
    }
    return n/b*m;
}
int main()
{
    int n,i;
    long long f[45];
    f[2]=2;
    for(i=3;i<=40;i++)
    {
        f[i]=gcd(f[i-1],i);
    }
    while(~scanf("%d",&n))
    {
         printf("%lld\n",f[n]-1);
    }
    return 0;
}

Problem H: Math

题解:此题数据有点虚了,换一种思路可以直接搞。提供本来自己思路的代码

代码:

#include 
 
using namespace std;
 
int T,n,k;
 
int p[]={2,3,5,7,11,13,17,19,23,29,31};
 
int sum[11],s[11];
 
void solve()
 
{
 
    memset(sum,0,sizeof(sum));
 
    memset(s,0,sizeof(s));
 
    if(n<2)
 
        return;
 
    int i,j;
 
    for(i=0;i<11;++i)
 
    {
 
        j=n;
 
        while(j)
 
        {
 
            sum[i]+=(j/=p[i]);
 
        }
 
    }
 
}
 
int calc()
 
{
 
    if(n<2)
 
        return 0;
 
    int ans=0x7fffffff;
 
    int i,j;
 
    for(i=0;i<11;++i)
 
    {
 
        while(!(k%p[i]))
 
        {
 
            k/=p[i];
 
            ++s[i];
 
        }
 
    }
 
    for(i=0;i<11;++i)
 
    {
 
        if(!s[i])
 
            continue;
 
        ans=min(ans,sum[i]/s[i]);
 
    }
 
    return ans;
 
}
 
int main()
 
{
 
    //freopen("test01.in","r",stdin);
 
    //freopen("test01.out","w",stdout);
 
    scanf("%d",&T);
 
    while(T--)
 
    {
 
        scanf("%d%d",&n,&k);
 
        //cin>>n>>k;
 
        solve();
 
        printf("%d\n",calc());
 
        //cout<

Problem I: Jinixin -> Mosu

题意:
在一个二维数组中寻找最长的递增序列长度,该二维数组长度最大可至1000*1000。
想法:
根据题意,大致确定这是一道搜索题,由于寻找的是“最长递增序列长度”,判断应该用迷宫类型的dfs,故直接套模板。

const int N=1000;
int p[N][N],vis[N][N],dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int max,n,m;
void dfs(int x,int y,int t)//迷宫类dfs模板,t为现在“递增序列”的长度
{
    int i,a,b;
    max=max>t?max:t;//更新max,max为目前“最长递增序列长度”
    for(i=0;i<4;i++)
    {
        a=x+dir[i][0];//根据所处X坐标,产生前进方向的X坐标
        b=y+dir[i][1];//根据所处Y坐标,产生前进方向的Y坐标
        if(a>=0&&a=0&&bp[x][y])//判断前进方向坐标是否合法,是否未走过,是否递增
        {
            vis[a][b]=1;//p[a][b]已经走过
            dfs(a,b,t+1);
            vis[a][b]=0;//p[a][b]重新标记未走过
        }
    }
}
int longestIncreaseRoute()
{
    int i,j;
    max=0;
    memset(vis,0,sizeof(vis));//vis用于判断该位置是否已经走过
    scanf("%d%d",&n,&m);
    for(i=0;i

注:寻找“最长递增序列长度”和寻找“最长递减序列长度”是等价的!
const int N=1000;
int p[N][N],vis[N][N],store[N][N],dir[4][3]={{-1,0},{1,0},{0,-1},{0,1}};//store数组用于记忆化
int dfs(int x,int y)
{
    int i,a,b,sum=1;//sum为从该位置出发的“最长递减序列长度”
    for(i=0;i<4;i++)
    {
        a=x+dir[i][0];
        b=y+dir[i][1];
        dir[i][2]=1;
        if(a>=0&&a=0&&bdir[i][2]?sum:dir[i][2];//四个方向中选取最大的值
    }
    store[x][y]=sum;//记忆化,从该位置(x,y)出发的“最长递减序列长度”
    return sum;
}
int longestIncreaseRoute()
{
    int i,j;
    int max=0;
    memset(vis,0,sizeof(vis));
    memset(store,0,sizeof(store));
    scanf("%d%d",&n,&m);
    for(i=0;istore[i][j]?max:store[i][j];//找出“最长递减序列长度”
        }
    }
    return max;
}
调用:longestIncreaseRoute();

“迷宫类dfs+记忆化”可以高效的解决本题。


代码:

#include
#include
#include
using namespace std;
const int M=1005;
int p[M][M],vis[M][M],store[M][M],dir[4][3]={{-1,0},{1,0},{0,-1},{0,1}};
int n,m;
int dfs(int x,int y)
{
    int i,a,b,sum=1;
    for(i=0;i<4;i++)
    {
        a=x+dir[i][0];
        b=y+dir[i][1];
        dir[i][2]=1;
        if(a>=0&&a=0&&bdir[i][2]?sum:dir[i][2];
    }
    store[x][y]=sum;
    return sum;
}
int path()
{
    int i,j,max=0;
    for(i=0;istore[i][j]?max:store[i][j];
        }
    }
    return max;
}
int main()
{
    //freopen("test1.in","r",stdin);
    //freopen("test1.out","w",stdout);
    int i,j;
    while(~scanf("%d%d",&n,&m))
    {
        memset(vis,0,sizeof(vis));
        memset(store,0,sizeof(store));
        for(i=0;i

Problem J: Jinixin's password

题解:

首先我们判断是否能由n个数构成m。

数据比如 3 0,1 19这种,就不能构成

然后我们就可以贪心了~

最小的数,肯定是由1000000000这种,然后从低位开始增加,直到达到m为止

而最大的数,则是由9999999999这种,从低位到高位,逐渐减小,直到变成m

比如 4 27这组数据

首先贪心最小的:


目前的数 目前的sum
1000 1
1009 10
1099 19
1899 27

贪心最大的:
目前的数 目前的sum
9999 36
9990 27

所以输出1899 9990

代码:

#include
#include
using namespace std;
 
int flag;
int n,m;
int Min[120];
int Max[120];
void getmin()
{
    int sum = 0;
    for(int i=1;i<=n;i++)
    {
        if(i==1)Min[i]=1;
        else Min[i]=0;
        sum += Min[i];
    }
    sum = m - sum;
    for(int i=n;i>=1;i--)
    {
        int T = min(sum,9-Min[i]);
        sum -= T;
        Min[i] += T;
    }
    if(Min[1]==0)flag = 1;
}
void getmax()
{
    int sum = 0;
    for(int i=1;i<=n;i++)
    {
        Max[i]=9;
        sum+=Max[i];
    }
    sum = sum - m;
    for(int i=n;i>=1;i--)
    {
        int T = min(sum,Max[i]);
        sum-=T;
        Max[i]-=T;
    }
    if(Max[1]==0)flag = 1;
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++)
    {
        scanf("%d%d",&n,&m);
        flag = 0;
        if(n==1&&m==0)
        {
            printf("0 0\n");
            continue;
        }
        if(n*9



你可能感兴趣的:(笔记)