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

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

#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

#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

#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

#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;
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));
}
char soft[maxn*10];
void add_edge(int x,int y)
{
edge[tot].v=y;
}
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();
{
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;
}
out[mp[name]]++;
in[mp[id]]++;
}
}
printf("Case %d: %d\n",cas++,topo());
}
return 0;
}

#### data:image/png;base64的使用

2017-06-17 11:46:16

#### 2014上海全国邀请赛1001(hdu 5090)

2014-11-02 22:45:27

#### 2014上海全国邀请赛1010(hdu 5099)

2014-11-03 00:08:11

#### hdu 5090 Game with Pearls 2014上海全国邀请赛——题目重现

2014-11-15 18:44:37

#### HDU 5090 Game with Pearls（上海邀请赛水题）

2014-11-14 20:50:47

#### 2014上海全国邀请赛1003(hdu 5092)

2014-11-02 23:16:38

#### 2014上海全国邀请赛1006(hdu 5095)

2014-11-02 23:52:23

#### 2014上海全国邀请赛 解题报告

2014-11-04 15:29:02

#### 2014上海全国邀请赛Maze

2015-01-23 00:40:11

#### hdu 5099

2014-11-04 11:22:12