ZOJ Monthly, September 2003【部分题解】

今天比赛做了一下这套题目。出了四道。两道水题,两道DP


比赛链接:http://vjudge.net/contest/view.action?cid=51404#problem/B


上来搞了一道水题之后就搞B题


题意很好理解,上来看了一下就懂了。以为是规律有循环节,没看wa那么多毅然决然提交,wa了一发。

 A = "^__^" and B = "T.T",C = BA = "T.T^__^".然后A=B,B=C,一直重复这个操作,问最后第n位的字母是什么?

写个程序跑出一些字符串的话会发现,我们可以求这些操作的一个逆操作,第一个长度4,第二个3,第三个7,第四个10,一次发现fib【i】=fib【i-1】+fib【i+1】。

那么我们按照这个过程跑回来,在7个字符中找就ok。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
long long a[100];
string ans="T.T^__^";
void isit()
{
    a[0]=4;a[1]=3;
    for(long long i=2;i<100;i++)
        a[i]=a[i-1]+a[i-2];
}
long long solve(long long x)
{
    while(x>7)
    {
        long long t;
        for(long long i=2;i<100;i++)
        {
            if(a[i]>=x)
            {
                //printf("--%d\n",a[i-1]);
                x-=a[i-1];break;
            }
        }
    }
    return x;
}
int main()
{
    long long x;
    isit();
    while(~scanf("%lld",&x))
    {
        long long p=solve(x);
        //printf("%d\n",p);
        printf("%c\n",ans[p-1]);
    }
    return 0;
}


第二道题目:K题,Match for Bonus

算是一个dp模型题目。

给出两个字符串,每个字母有一个价值,两个字母相同的话把两个字符串中的这个字母以及之前的字符全部删除,问得到最大价值。


分析:LCS模型,推一下发现是价值最大的也是一个公共子序列。那么我们就可以用公共子序列转移了


定义dp【i】【j】:第一个串从开始到第 i 个位置,第二个串从开始到第 j 个位置的的最大价值公共子序列

那么转移方程:

dp【i】【j】=max(dp【i-1】【j-1】+(val【i-1】),dp【i-1】【j】,dp【i】【j-1】)


题目很水,但是坑点是没有给出数据范围,开的数组小了竟然返回wa。。。。坑了啊又!

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <map>
using namespace std;
const int N = 3000;
int dp[N][N];
char a[N],b[N];
map<char,int> m;
int main()
{
    //freopen("Input.txt","r",stdin);
    int n;
    while(~scanf("%d",&n))
    {
        char c;
        int x;
        for(int i=0; i<n; i++)
        {
            getchar();
            scanf("%c %d",&c,&x);
            if(m[c])
                continue;
            m[c]=x;
        }
        memset(dp,0,sizeof(dp));
        scanf("%s%s",a+1,b+1);
        int la=strlen(a+1),lb=strlen(b+1);
        //printf("%d %d\n",la,lb);
        for(int i=1;i<=la;i++)
        {
            for(int j=1;j<=lb;j++)
            {
                if(a[i] == b[j])
                    dp[i][j] =max(dp[i][j], dp[i-1][j-1] + m[ a[i] ]);
                else
                {
                    dp[i][j] = max(dp[i][j],dp[i][j-1]);
                    dp[i][j] = max(dp[i][j],dp[i-1][j]);
                }
            }
        }
        printf("%d\n",dp[la][lb]);
        m.clear();
    }
    return 0;
}


第三道题目:H题 Hang Up the System


题意:给出一些电脑的进程数n,每个进程有优先级(n<16),一看就是状态压缩啊,哈哈,然后有一些进程是冲突的,问不冲突的情况下可以跑的进程的优先级的和的最大值是多少?


用状态压缩表示当前状态可不可选,然后判断冲突,求一个最大的优先级即可。


代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <map>
#include <cmath>
using namespace std;
#define Del(a,b) memset(a,b,sizeof(a))

map<string,int> m;
int val[200];
int lict[2000];
int main()
{
    //freopen("Input.txt","r",stdin);
    int n,cas=1;
    while(~scanf("%d",&n) && n)
    {
        string s;
        int x,tt=1;
        Del(val,0);
        for(int i=0;i<n;i++)
        {
            cin>>s>>x;
            if(m[s]){}
            else
                m[s]=tt++;
            val[m[s]]=x;
        }
        Del(lict,0);
        int q;
        scanf("%d",&q);
        getchar();
        for(int i=0;i<q;i++)
        {

            string ps;
            getline(cin,ps);
            //cout<<ps<<endl;
            int tmp=0;string stmp="";
            for(int j=0;j<ps.size();j++)
            {
                if(ps[j]!=' ')
                    stmp+=ps[j];
                else
                {
                    //cout<<"---"<<stmp<<endl;
                    tmp+=(1<<(m[stmp]-1));
                    stmp="";
                }
            }
            if(stmp!="")
                tmp+=pow(2,(m[stmp]-1));
            lict[i]=tmp;
        }
        int ans=0;
        bool flag[20];
        for(int st=0;st<1<<(n);st++)
        {
            Del(flag,0);
            int tmp=0,ok=1;
            for(int j=0;j<q;j++)
            {
                int aa=st&lict[j];
                //cout<<aa<<" "<<lict[j]<<endl;
                if(aa==lict[j])
                {
                    ok=0;
                    break;
                }
            }
            if(ok)
            {
                int sos=st;
                //cout<<"---"<<sos<<" ";
                for(int k=0;k<17;k++)
                {
                    if(sos&(1<<k))
                        tmp+=val[k+1];
                }

            }
            ans=max(ans,tmp);
        }
        printf("System %d: %d\n",cas++,ans);
        m.clear();
    }
    return 0;
}


你可能感兴趣的:(压缩,namespace,动态规划,iostream,ICPC)