1. 程式人生 > >2014上海全國邀請賽題解 HDOJ 5090-5099

2014上海全國邀請賽題解 HDOJ 5090-5099

HDOJ 5090

水題,從小到大排序,可以填充達到符合條件的,先填充好,填充之後進行調整。

#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 1e2+10;
int t, n, k, ia[MAXN];

int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &k);
        bool flag = true;
        for(int i=1; i<=n; ++i)
        {
            scanf("%d", ia+i);
        }
        sort(ia+1, ia+n+1);
        for(int i=1; i<=n; ++i)
        {
            if(i < ia[i])
            {
                flag = false;
                break;
            }
            if(i == ia[i])
            {
                continue;
            }
            if(0 == (i-ia[i])%k)
            {
                ia[i] = i;
            }
            else
            {
                int tp = 1;
                for(int j=i+1; j<=n; ++j)
                {
                    if(0 == (j-ia[i])%k)
                    {
                        ia[i] = j;
                        tp = 0;
                        --i;
                        break;
                    }
                }
                if(tp)
                {
                    flag = false;
                    break;
                }
            }
            sort(ia+1, ia+n+1);
        }
        printf("%s\n", flag ? "Jerry" : "Tom");
    }
    return 0;
}

HDOJ 5092

題意:每行取一個數,使總和最小,取了mp[i][j]之後,只能在該點左下,正下,右下三個位置裡面取下一個點,記錄路徑,要注意儘量靠右。

分析:一個典型的dp

#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 1e2+10;
const int INF = 0x7fffffff;
int t, m, n, dp[MAXN][MAXN];
int s[MAXN][MAXN], mp[MAXN][MAXN], icase = 1;

void output(int i, int j)
{
    if(0 == i)
    {
        return ;
    }
    if(1 == s[i][j])
    {
        output(i-1, j-1);
        printf("%d ", j-1);
    }
    else if(2 == s[i][j])
    {
        output(i-1, j);
        printf("%d ", j);
    }
    else if(3 == s[i][j])
    {
        output(i-1, j+1);
        printf("%d ", j+1);
    }
}

int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &m);
        memset(dp, 0, sizeof(dp));
        memset(mp, 0, sizeof(mp));
        memset(s, 0, sizeof(s));
        for(int i=1; i<=n; ++i)
        {
            for(int j=1; j<=m; ++j)
            {
                scanf("%d", &mp[i][j]);
            }
        }
        for(int i=1; i<=m; ++i)
        {
            dp[1][i] = mp[1][i];
        }
        for(int i=2; i<=n; ++i)
        {
            for(int j=1; j<=m; ++j)
            {
                int mn = INF;
                if(j>=2 && dp[i-1][j-1] <= mn)
                {
                    mn = dp[i-1][j-1];
                    s[i][j] = 1;
                }
                if(dp[i-1][j] <= mn)
                {
                    mn = dp[i-1][j];
                    s[i][j] = 2;
                }
                if(j<=m-1 && dp[i-1][j+1] <= mn)
                {
                    mn = dp[i-1][j+1];
                    s[i][j] = 3;
                }
                dp[i][j] = mn + mp[i][j];
            }
        }
        int mn = INF, id = 0;
        for(int i=1; i<=m; ++i)
        {
            if(dp[n][i] <= mn)
            {
                mn = dp[n][i];
                id = i;
            }
        }
/*
        printf("%d\n", mn);
        for(int i=1; i<=n; ++i)
        {
            for(int j=1; j<=m; ++j)
            {
                printf("%d ", dp[i][j]);
            }
            printf("\n");
        }
*/
        printf("Case %d\n", icase++);
        output(n, id);
        printf("%d\n", id);
    }
    return 0;
}

HDOJ 5093

分析:二分圖。

隊友寫的,沒細看,貼個隊友的程式碼,之後有空再看。

程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int match[1260];
char map[60][60];
int pic[1260][60];
int vis[1260];
int m,n;		
int nx=0,ny[60],nk=0,flag=0,yvis[60];
int dp(int now)
{
	int i;
	for(i=0;pic[now][i]!=-1;i++)
	{
		int t=pic[now][i];
		if(vis[t]==1)
			continue;
		vis[t]=1;
		if(match[t]==-1||dp(match[t]))
		{
			match[t]=now;
			return 1;
		}
	}
	return 0;
}
int main()
{
	//freopen("D:\\in.txt","r",stdin);
	int t,i,j;
	cin>>t;
	while(t--)
	{
		cin>>m>>n;
		for(i=0;i<m;i++)
			scanf("%s",map[i]);
		memset(yvis,0,sizeof(yvis));
		for(i=0;i<n;i++)
			ny[i]=i;
		nx=nk=0;
		flag=0;
		memset(pic,-1,sizeof(pic));
		for(i=0;i<m;i++)
		{
			for(j=0;j<n;j++)
			{
				if(map[i][j]=='*')
				{
					yvis[j]=1;
					pic[nx][flag++]=ny[j];
				}
				if(map[i][j]=='#')
				{
					if(flag)
					{
						nx++;
						flag=0;
					}
					if(yvis[j])
					{
						ny[j]=n+nk;
						nk++;
						yvis[j]=0;
					}
				}
			}
			if(flag)
			{
				nx++;
				flag=0;
			}
		}
		int ans=0;
		memset(match,-1,sizeof(match));
		for(i=0;i<=nx;i++)
		{
			memset(vis,0,sizeof(vis));
			if(dp(i))
				ans++;
		}
		cout<<ans<<endl;
	}
}

HDOJ 5094

分析:BFS+狀壓(不然會MLE),wa點:一個位置可能有幾把不同的鑰匙。

#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 55;
int n, m, p, k, s, mk[MAXN][MAXN];
int vis[1<<11][MAXN][MAXN];
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
struct P
{
    int x, y, time, key;
};
map<int, int> mp;

int BFS()
{
    memset(vis, 0, sizeof(vis));
    queue<P> que;
    P s; s.x = s.y = 1;
    s.key = s.time = 0;
    if(mk[s.x][s.y])
    {
        s.key = mk[s.x][s.y];
    }
    vis[s.key][s.x][s.y] = 1;
    que.push(s);
    while(!que.empty())
    {
        P u = que.front();
        que.pop();
        if(u.x==n && u.y==m)
        {
            return u.time;
        }
        for(int i=0; i<4; ++i)
        {
            P v;
            v.x = u.x + dir[i][0];
            v.y = u.y + dir[i][1];
            if(v.x<1 || v.x>n || v.y<1 || v.y>m)
            {
                continue;
            }
            int q = 51*51*51*u.x + 51*51*u.y + 51*v.x + v.y;
            int tp = mp[q];
            if(4e8 == tp)
            {
                continue;
            }
            if(0 == tp)
            {
                v.time = u.time + 1;
                v.key = u.key;
                if(mk[v.x][v.y] && 0==(mk[v.x][v.y]&u.key))
                {
                    v.key += mk[v.x][v.y];
                }
                if(vis[v.key][v.x][v.y])
                {
                    continue;
                }
                vis[v.key][v.x][v.y] = 1;
                que.push(v);
            }
            else
            {
                if(u.key & (1<<tp))
                {
                    v.time = u.time + 1;
                    v.key = u.key;
                    if(mk[v.x][v.y] && 0==(mk[v.x][v.y]&u.key))
                    {
                        v.key += mk[v.x][v.y];
                    }
                    if(vis[v.key][v.x][v.y])
                    {
                        continue;
                    }
                    vis[v.key][v.x][v.y] = 1;
                    que.push(v);
                }
            }
        //    printf("%d %d %d %d\n", v.x, v.y, v.time, v.key);
        }
    }
    return -1;
}

int main()
{
    while(~scanf("%d%d%d", &n, &m, &p))
    {
        scanf("%d", &k);
        mp.clear();
        memset(mk, 0, sizeof(mk));
        while(k--)
        {
            int ux, uy, vx, vy, g, hx, hy;
            scanf("%d%d%d%d%d", &ux, &uy, &vx, &vy, &g);
            hx = 51*51*51*ux + 51*51*uy + 51*vx + vy;
            hy = 51*51*51*vx + 51*51*vy + 51*ux + uy;
            if(0 == g) g = 4e8;
            mp[hx] = mp[hy] = g;
        }
        scanf("%d", &s);
        while(s--)
        {
            int x, y, q;
            scanf("%d%d%d", &x, &y, &q);
            mk[x][y] += (1<<q);
        }
        printf("%d\n", BFS());
    }
    return 0;
}

HDOJ 5095

分析:水題,寫的時候注意處理-1,0,1就差不多了,還有首位為正,不需要+。

程式碼:

#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long lint;
const int MAXN = 20;
char ch[] = {'p', 'q', 'r', 'u', 'v', 'w', 'x', 'y', 'z'};
int ia[MAXN], t;

int main()
{
    scanf("%d", &t);
    while(t--)
    {
        for(int i=0; i<10; ++i)
        {
            scanf("%d", ia+i);
        }
        int first = 1, zero = 1;
        for(int i=0; i<10; ++i)
        {
            if(0 == ia[i])
            {
                continue;
            }
            zero = 0;
            if(ia[i] < 0)
            {
                if(-1 == ia[i])
                {
                    if(i < 9)
                    {
                        printf("-");
                    }
                    else
                    {
                        printf("-1");
                    }
                }
                else
                {
                    printf("%d", ia[i]);
                }
                first = 0;
            }
            else
            {
                if(1 == ia[i])
                {
                    if(!first)
                    {
                        printf("+");
                    }
                    first = 0;
                    if(i == 9)
                    {
                        printf("1");
                    }
                }
                else
                {
                    if(!first)
                    {
                        printf("+");
                    }
                    first = 0;
                    printf("%d", ia[i]);
                }
            }
            if(i < 9)
            {
                printf("%c", ch[i]);
            }
        }
        if(zero) printf("0");
        printf("\n");
    }
    return 0;
}

HDOJ 5098

隊友寫的,貼個程式碼,之後補。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
char info[1010][1030];
int need[1010][1010],nn[1010];
int num[1010];
int res[1010],ns;   //ns為軟體數量,res表示是否要重啟
map<string,int> list;
int dfs(int now)
{
	if(num[now]!=-1)
		return num[now];
	int ma=0,i;
	for(i=0;need[now][i]!=-1;i++)
	{
		int t=need[now][i];
		if(res[t])
			ma=max(ma,dfs(t)+1);
		else
			ma=max(ma,dfs(t));
	}
	num[now]=ma;
	return num[now];
}
int main()
{
	//freopen("D:\\in.txt","r",stdin);
	int t,i,j,count=1;
	cin>>t;
	getchar();
	getchar();
	while(t--)
	{
		memset(info,0,sizeof(info));
		list.clear();
		memset(res,0,sizeof(res));
		i=0;
		while(gets(info[i]))                     //開始資料處理
		{
			if(strlen(info[i])==0)
				break;
			j=0;
			while(info[i][j]!='*'&&info[i][j]!=':')
				j++;
			list[string(info[i],j)]=i;
			if(info[i][j]=='*')
				res[i]=1;
			i++;
		}
		ns=i;
		memset(need,-1,sizeof(need));
		memset(nn,0,sizeof(nn));
		for(i=0;i<ns;i++)
		{
			int s=0;
			while(info[i][s]!=' '&&s!=strlen(info[i]))
				s++;
			int e=s;
			while(e!=strlen(info[i]))
			{
				s=e;
				e++;
				while(e!=strlen(info[i])&&info[i][e]!=' ')
					e++;
				need[i][nn[i]++]=list[string(info[i]+s+1,e-s-1)];
			}
		}                                                               //資料處理結束,need[i]表示i的依賴包,到-1結束
		memset(num,-1,sizeof(num));
		int ma=0;
		for(i=0;i<ns;i++)
		{
			if(res[i])
				ma=max(ma,dfs(i)+1);
			else
				ma=max(ma,dfs(i));
		}
		printf("Case %d: %d\n",count++,ma);
	}
}

HDOJ 5099

分析:水題,字串比較。

程式碼:

#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 2e3+10;
char cha[MAXN], chb[MAXN];
int t, icase = 1;

int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%s%s", cha, chb);
       // puts(cha); puts(chb);
       printf("Case %d: ", icase++);
       if(cha[0] > chb[0])
       {
           printf("> ");
       }
       else if(cha[0] < chb[0])
       {
           printf("< ");
       }
       else
       {
           printf("= ");
       }
       if(cha[1] != chb[1])
       {
           cha[5] = chb[5] = '\0';
       }
       int ret = strcmp(cha+2, chb+2);
       if(ret > 0)
       {
           printf(">");
       }
       else if(ret < 0)
       {
           printf("<");
       }
       else
       {
           printf("=");
       }
       printf("\n");
    }
    return 0;
}