2014上海全国邀请赛(hdu 5090 - 5099)dp+线段树+拓扑排序+bfs(状态压缩)

原创 2015年07月10日 10:12:43

Game with Pearls
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1431 Accepted Submission(s): 527

Problem Description
Tom and Jerry are playing a game with tubes and pearls. The rule of the game is:

1) Tom and Jerry come up together with a number K.

2) Tom provides N tubes. Within each tube, there are several pearls. The number of pearls in each tube is at least 1 and at most N.

3) Jerry puts some more pearls into each tube. The number of pearls put into each tube has to be either 0 or a positive multiple of K. After that Jerry organizes these tubes in the order that the first tube has exact one pearl, the 2nd tube has exact 2 pearls, …, the Nth tube has exact N pearls.

4) If Jerry succeeds, he wins the game, otherwise Tom wins.

Write a program to determine who wins the game according to a given N, K and initial number of pearls in each tube. If Tom wins the game, output “Tom”, otherwise, output “Jerry”.

Input
The first line contains an integer M (M<=500), then M games follow. For each game, the first line contains 2 integers, N and K (1 <= N <= 100, 1 <= K <= N), and the second line contains N integers presenting the number of pearls in each tube.

Output
For each game, output a line containing either “Tom” or “Jerry”.

Sample Input

2
5 1
1 2 3 4 5
6 2
1 2 3 4 5 5

Sample Output

Jerry
Tom

题意:有n个盒子,每个盒子初始有1-n个球,现在要在盒子里添加k的倍数个球,使得最后盒子排序后,第一个盒子有1个球,第n个盒子有n个球
思路:暴力,1-n每个数字是由谁得来的,只要有一个就可以,如果有多个,那么如果满足题意条件,剩下的也必然能转化成其他的

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=510;
int a[maxn];
int N,K;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&N,&K);
        memset(a,0,sizeof(a));
        for(int i=1;i<=N;i++)
        {
            int x;
            scanf("%d",&x);
            a[x]++;
        }
        bool flag=true;
        for(int i=1;i<=N;i++)
        {
            bool flag1=false;
            for(int j=0;i-K*j>=0;j++)
            {
                if(a[i-K*j])
                {
                    flag1=true;
                    a[i-j*K]--;
                    break;
                }
            }
            if(!flag1){flag=false;break;}
        }
        if(flag)printf("Jerry\n");
        else printf("Tom\n");
    }
    return 0;
}

Beam Cannon
Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 644 Accepted Submission(s): 234

Problem Description
Recently, the γ galaxies broke out Star Wars. Each planet is warring for resources. In the Star Wars, Planet X is under attack by other planets. Now, a large wave of enemy spaceships is approaching. There is a very large Beam Cannon on the Planet X, and it is very powerful, which can destroy all the spaceships in its attack range in a second. However, it takes a long time to fill the energy of the Beam Cannon after each shot. So, you should make sure each shot can destroy the enemy spaceships as many as possible.

To simplify the problem, the Beam Cannon can shot at any area in the space, and the attack area is rectangular. The rectangle parallels to the coordinate axes and cannot rotate. It can only move horizontally or vertically. The enemy spaceship in the space can be considered as a point projected to the attack plane. If the point is in the rectangular attack area of the Beam Cannon(including border), the spaceship will be destroyed.

Input
Input contains multiple test cases. Each test case contains three integers N(1<=N<=10000, the number of enemy spaceships), W(1<=W<=40000, the width of the Beam Cannon’s attack area), H(1<=H<=40000, the height of the Beam Cannon’s attack area) in the first line, and then N lines follow. Each line contains two integers x,y (-20000<=x,y<=20000, the coordinates of an enemy spaceship).

A test case starting with a negative integer terminates the input and this test case should not to be processed.

Output
Output the maximum number of enemy spaceships the Beam Cannon can destroy in a single shot for each case.

Sample Input

2 3 4
0 1
1 0
3 1 1
-1 0
0 1
1 0
-1

Sample Output

2
2

题意:有n个星星,一个W*H的框,问最多能框住多少星星
思路:线段树扫描线,将每个点抽象成两条线段,我是按y轴方向扫的,这样做的原因是每个点的影响范围有限,见下图。
这里写图片描述
图中A点可以影响到的矩形是(x,x+W)范围内的,A点抽象成了1,-1这两条线,也就是说明,他纵向能影响到的是这个范围。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=40010;
const int BIT=20000;
int N,W,H;
struct Segment
{
    int l,r,h,t;
    Segment()=default;
    Segment(int a,int b,int c,int d):l(a),r(b),h(c),t(d){}
    bool operator<(const Segment &a)const
    {
        return h<a.h;
    }
}s[maxn];
struct IntervalTree
{
    int sum[maxn<<2];
    int setv[maxn<<2];
    void build(int o,int l,int r)
    {
        sum[o]=setv[o]=0;
        if(l==r)return ;
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build(o<<1|1,mid+1,r);
    }
    void  pushdown(int o)
    {
        if(setv[o])
        {
            setv[o<<1]+=setv[o];
            setv[o<<1|1]+=setv[o];
            sum[o<<1]+=setv[o];
            sum[o<<1|1]+=setv[o];
            setv[o]=0;
        }
    }
    void pushup(int o)
    {
        sum[o]=max(sum[o<<1],sum[o<<1|1]);
    }
    void update(int o,int l,int r,int q1,int q2,int x)
    {
        if(q1<=l&&r<=q2)
        {
            sum[o]+=x;
            setv[o]+=x;
            return ;
        }
        pushdown(o);
        int mid=(l+r)>>1;
        if(q1<=mid)update(o<<1,l,mid,q1,q2,x);
        if(q2>mid)update(o<<1|1,mid+1,r,q1,q2,x);
        pushup(o);
    }
}tree;
int main()
{
    while(scanf("%d",&N)!=EOF,N>0)
    {
        scanf("%d%d",&W,&H);
        int num=0;
        for(int i=0;i<N;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            x+=BIT,y+=BIT;
            int lx=(x+W>40000?40000:x+W);
            s[num++]=Segment(x,lx,y,1);
            s[num++]=Segment(x,lx,y+H,-1);
        }
        int ans=0;
        sort(s,s+num);
        tree.build(1,0,40000);
        for(int i=0;i<num;i++)
        {
            tree.update(1,0,40000,s[i].l,s[i].r,s[i].t);
            ans=max(ans,tree.sum[1]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

Seam Carving
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 797 Accepted Submission(s): 323

Problem Description
Fish likes to take photo with his friends. Several days ago, he found that some pictures of him were damaged. The trouble is that there are some seams across the pictures. So he tried to repair these pictures. He scanned these pictures and stored them in his computer. He knew it is an effective way to carve the seams of the images He only knew that there is optical energy in every pixel. He learns the following principle of seam carving. Here seam carving refers to delete through horizontal or vertical line of pixels across the whole image to achieve image scaling effect. In order to maintain the characteristics of the image pixels to delete the importance of the image lines must be weakest. The importance of the pixel lines is determined in accordance with the type of scene images of different energy content. That is, the place with the more energy and the richer texture of the image should be retained. So the horizontal and vertical lines having the lowest energy are the object of inspection. By constantly deleting the low-energy line it can repair the image as the original scene.

这里写图片描述
For an original image G of m*n, where m and n are the row and column of the image respectively. Fish obtained the corresponding energy matrix A. He knew every time a seam with the lowest energy should be carved. That is, the line with the lowest sum of energy passing through the pixels along the line, which is a 8-connected path vertically or horizontally.

Here your task is to carve a pixel from the first row to the final row along the seam. We call such seam a vertical seam.

Input
There several test cases. The first line of the input is an integer T, which is the number of test cases, 0

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=110;
const int INF=0x3f3f3f3f;
int N,M;
int dp[maxn][maxn];
int a[maxn][maxn];
int path[maxn][maxn];

int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&N,&M);
        for(int i=1;i<=N;i++)
            for(int j=1;j<=M;j++)scanf("%d",&a[i][j]);
        memset(dp,INF,sizeof(dp));
        memset(path,-1,sizeof(path));
        for(int i=1;i<=M;i++)dp[N][i]=a[N][i];
        for(int i=N-1;i>=1;i--)
        {
            for(int j=1;j<=M;j++)
            {
                dp[i][j]=dp[i+1][j]+a[i][j];
                path[i][j]=j;
                if(j-1>0&&dp[i+1][j-1]+a[i][j]<dp[i][j])
                {
                    dp[i][j]=dp[i+1][j-1]+a[i][j];
                    path[i][j]=j-1;
                }
                if(j+1<=M&&dp[i+1][j+1]+a[i][j]<=dp[i][j])
                {
                    dp[i][j]=dp[i+1][j+1]+a[i][j];
                    path[i][j]=j+1;
                }
            }
        }
        int ans,maxv=INF;
        for(int i=1;i<=M;i++)
            if(dp[1][i]<=maxv)maxv=dp[1][i],ans=i;
        bool first=true;
        printf("Case %d\n",cas++);
        for(int i=1;i<=N;i++)
        {
            printf("%d",ans);
            if(i!=N)printf(" ");
            else printf("\n");
            ans=path[i][ans];
        }
    }
    return 0;
}

Maze
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 100000/100000 K (Java/Others)
Total Submission(s): 763 Accepted Submission(s): 273

Problem Description
This story happened on the background of Star Trek.

Spock, the deputy captain of Starship Enterprise, fell into Klingon’s trick and was held as prisoner on their mother planet Qo’noS.

The captain of Enterprise, James T. Kirk, had to fly to Qo’noS to rescue his deputy. Fortunately, he stole a map of the maze where Spock was put in exactly.

The maze is a rectangle, which has n rows vertically and m columns horizontally, in another words, that it is divided into n*m locations. An ordered pair (Row No., Column No.) represents a location in the maze. Kirk moves from current location to next costs 1 second. And he is able to move to next location if and only if:

Next location is adjacent to current Kirk’s location on up or down or left or right(4 directions)
Open door is passable, but locked door is not.
Kirk cannot pass a wall

There are p types of doors which are locked by default. A key is only capable of opening the same type of doors. Kirk has to get the key before opening corresponding doors, which wastes little time.

Initial location of Kirk was (1, 1) while Spock was on location of (n, m). Your task is to help Kirk find Spock as soon as possible.

Input
The input contains many test cases.

Each test case consists of several lines. Three integers are in the first line, which represent n, m and p respectively (1<= n, m <=50, 0<= p <=10).
Only one integer k is listed in the second line, means the sum number of gates and walls, (0<= k <=500).

There are 5 integers in the following k lines, represents xi1, yi1, xi2, yi2, gi; when gi >=1, represents there is a gate of type gi between location (xi1, yi1) and (xi2, yi2); when gi = 0, represents there is a wall between location (xi1, yi1) and (xi2, yi2), ( | xi1 - xi2 | + | yi1 - yi2 |=1, 0<= gi <=p )

Following line is an integer S, represent the total number of keys in maze. (0<= S <=50).

There are three integers in the following S lines, represents xi1, yi1 and qi respectively. That means the key type of qi locates on location (xi1, yi1), (1<= qi<=p).

Output
Output the possible minimal second that Kirk could reach Spock.

If there is no possible plan, output -1.

Sample Input

4 4 9
9
1 2 1 3 2
1 2 2 2 0
2 1 2 2 0
2 1 3 1 0
2 3 3 3 0
2 4 3 4 1
3 2 3 3 0
3 3 4 3 0
4 3 4 4 0
2
2 1 2
4 2 1

Sample Output

14

题意:有一个迷宫,格子之间有门或墙,有p种门,S个钥匙,问从(1,1)走到(n,m)最短时间
思路:还是普通的bfs,只不过是加一个状态,保存当前有哪些钥匙

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=55;
int N,M,P,K,S;
struct node
{
    int x,y,t;
    int S;
    node()=default;
    node(int a,int b,int c,int d):x(a),y(b),t(c),S(d){}
};
int gate[maxn][maxn][maxn][maxn];
int key[maxn][maxn];
bool vis[maxn][maxn][1<<11];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int BFS(int sx,int sy)
{
    memset(vis,0,sizeof(vis));
    queue<node> q;
    node B;
    if(key[sx][sy])
        q.push(node(sx,sy,0,key[sx][sy]));
    else q.push(node(sx,sy,0,0));
    while(!q.empty())
    {
        node A=q.front();q.pop();
        for(int i=0;i<4;i++)
        {
            int tx=A.x+dx[i];
            int ty=A.y+dy[i];
            if(tx<1||tx>N||ty<1||ty>M)continue;
            int g=gate[A.x][A.y][tx][ty];
            if(g==0)continue;
            if(g>0)
            {
                if(!(A.S&(1<<(g-1))))
                    continue;
            }
            int tmpS=A.S;
            if(key[tx][ty])tmpS|=key[tx][ty];
            if(vis[tx][ty][tmpS])continue;
            vis[tx][ty][tmpS]=1;
            if(tx==N&&ty==M)return A.t+1;
            q.push(node(tx,ty,A.t+1,tmpS));
        }
    }
    return -1;
}
int main()
{
    while(scanf("%d%d%d",&N,&M,&P)!=EOF)
    {
        scanf("%d",&K);
        memset(gate,-1,sizeof(gate));
        memset(key,0,sizeof(key));
        for(int i=1;i<=K;i++)
        {
            int a,b,c,d,e;
            scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
            gate[a][b][c][d]=gate[c][d][a][b]=e;
        }
        scanf("%d",&S);
        for(int i=1;i<=S;i++)
        {
            int x,y,t;
            scanf("%d%d%d",&x,&y,&t);
            key[x][y]|=(1<<(t-1));
        }
        printf("%d\n",BFS(1,1));
    }
    return 0;
}

Smart Software Installer
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 471 Accepted Submission(s): 143

Problem Description
The software installation is becoming more and more complex. An automatic tool is often useful to manage this process. An IT company is developing a system management utility to install a set of software packages automatically with the dependencies. They found that reboot is often required to take effect after installing some software. A software package cannot be installed until all software packages it depends on are installed and take effect.

In the beginning, they implemented a simple installation algorithm, but the system would reboot many times during the installation process. This will have a great impact on the user experience. After some study, they think that this process can be further optimized by means of installing as much packages as possible before each reboot.

Now, could you please design and implement this algorithm for them to minimize the number of restart during the entire installation process?

Input
The first line is an integer n (1 <= n <= 100), which is the number of test cases. The second line is blank. The input of two test cases is separated by a blank line.

Each test case contains m (1 <= n <= 1000) continuous lines and each line is no longer than 1024 characters. Each line starts with a package name and a comma (:). If an asterisk (*) exists between the package name and the comma, the reboot operation is required for this package. The remaining line is the other package names it depends on, separated by whitespace. Empty means that there is no dependency for this software. For example, “a: b” means package b is required to be installed before package a. Package names consist of letters, digits and underscores, excluding other special symbols.

Assume all packages here need to be installed and all referenced packages will be listed in an individual line to define the reboot property. It should be noted that cyclic dependencies are not allowed in this problem.

Output
For each test case, you should output a line starting with “Case #: ” (# is the No. of the test case, starting from 1) and containing the reboot count for this test case. (Refer to the sample format)

Sample Input

2

glibc:
gcc*: glibc

uefi*:
gcc*:
raid_util*: uefi
gpu_driver*: uefi
opencl_sdk: gpu_drivergcc

Sample Output

Case 1: 1
Case 2: 2

题意:告诉你软件之间的依赖关系,带*的是需要重启才生效的,问最小重启几次。
思路:转自:hdu5098
很神奇,相当于先把不需要重启的全部按完,然后把暴露在最外面的需要重启的一块按完,重启一次

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<sstream>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=10240;
int in[maxn],out[maxn],reboot[maxn];
int tot,cnt;
int head[maxn];
map<string,int> mp;
struct node
{
    int v,next;
}edge[maxn];
void init()
{
    tot=cnt=0;
    mp.clear();
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    memset(reboot,0,sizeof(reboot));
    memset(head,-1,sizeof(head));
}
char soft[maxn*10];
void add_edge(int x,int y)
{
    edge[tot].v=y;
    edge[tot].next=head[x];
    head[x]=tot++;
}
int topo()
{
    queue<int> q1,q2;
    for(int i=1;i<=cnt;i++)
    {
        if(in[i]==0)
        {
            if(reboot[i])q2.push(i);
            else q1.push(i);
        }
    }
    int ans=0;
    while(!q1.empty()||!q2.empty())
    {
        if(q1.empty()&&!q2.empty())
        {
            ans++;
            while(!q2.empty())
            {
                q1.push(q2.front());
                q2.pop();
            }
        }
        while(!q1.empty())
        {
            int u=q1.front();q1.pop();
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].v;
                in[v]--;
                if(in[v]==0)
                {
                    if(reboot[v])q2.push(v);
                    else q1.push(v);
                }
            }
        }
    }
    return ans;
}
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    getchar();getchar();
    string s;
    while(T--)
    {
        init();
        while(getline(cin,s))
        {
            if(s[0]=='\0')break;
            istringstream ss(s);
            ss>>soft;
            int len=strlen(soft);
            int flag=0;
            if(soft[len-2]=='*')
            {
                flag=1;
                soft[len-2]='\0';
            }
            else soft[len-1]='\0';
            string id(soft),name;
            if(mp.find(id)==mp.end())
            {
                mp[id]=++cnt;
            }
            reboot[mp[id]]=flag;
            while(ss>>name)
            {
                if(mp.find(name)==mp.end())
                {
                    mp[name]=++cnt;
                }
                add_edge(mp[name],mp[id]);
                out[mp[name]]++;
                in[mp[id]]++;
            }
        }
        printf("Case %d: %d\n",cas++,topo());
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

2014上海网络赛1004||hdu5045 contest【状态压缩dp】

题意:m小时之间每个小时有新出的一个题供n个人中的一个人做,每个人做出的概率已知,每一时刻任意两个人做出的题数之差不得多于1个,问最多答题的个数 之前的状压都是三重循环是同一个数来的,然而这个题让我...

hdu 5195(拓扑排序+线段树优化)

DZY Loves Topological Sorting Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072...

HDU 5195 DZY Loves Topological Sorting (拓扑排序+线段树)

题目地址:HDU 5195 简直受不了了。。BC第二题都开始线段树+拓扑排序了。。。 这题很容易想到拓扑排序过程中贪心,但是贪心容易TLE,所以需要用数据结构去维护,我用的是线段树维护。每次找入度...

hdu 5092 Seam Carving 2014上海全国邀请赛——题目重现

这一题是看了别人的blog才知道题目中求的path是长啥样的,可我还是木有从timi

2014上海全国邀请赛I题 Smart Software Installer(hdu5098)(top排序)

SmartSoftware Installer Time Limit: 2000/1000 MS(Java/Others)    Memory Limit: 65536/65536 K (Java/O...

【bzoj 3832】 [Poi2014] Rally (权值线段树+拓扑排序)

乘一叶扁舟随风漾,谁家秋雁知落英?

【BZOJ】【P2584】【Wc2012】【memory】【题解】【线段树+扫描线+拓扑排序】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2584 首先考虑第二问 显然只向一个方向移动一定有解 假设向上 显然构成了一个DAG图,...

hdu 5025 Saving Tang Monk[状态压缩bfs]( 2014 ACM/ICPC Asia Regional Guangzhou Online)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5025

HDU 5097 Page Rank(矩阵模拟)——2014上海全国邀请赛——题目重现(感谢上海大学提供题目)

传送门Page RankTime Limit: 3000/1500 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others)Tot...

【HDU】2014上海全国邀请赛——题目重现(感谢上海大学提供题目) 题解

写在最前:感谢bin神~ A:【HDU
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)