kebabTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1273 Accepted Submission(s): 532 Problem Description Almost everyone likes kebabs nowadays (Here a kebab means pieces of meat grilled on a long thin stick). Have you, however, considered about the hardship of a kebab roaster while enjoying the delicious food? Well, here‘s a chance for you to help the poor roaster Now N customers is coming. Customer i will arrive at time si (which means the roaster cannot serve customer i until time si). He/She will order ni kebabs, each one of which requires a total amount of ti unit time to get it well-roasted, and want to get them Oh, I forgot to say that the roaster needs not to roast a single kebab in a successive period of time. That means he can divide the whole ti unit time into k (1<=k<=ti) parts such that any two adjacent parts don’t have to be successive in time. He can also Input There are multiple test cases. The first line of each case contains two positive integers N and M. N is the number of customers and M is the maximum kebabs the grill can roast at the same time. Then follow N lines each describing one customer, containing four There is a blank line after each input block. Restriction: 1 <= N <= 200, 1 <= M <= 1,000 1 <= ni, ti <= 50 1 <= si < ei <= 1,000,000 Output If the roaster can satisfy all the customers, output “Yes” (without quotes). Otherwise, output “No”. Sample Input 2 10 1 10 6 3 2 10 4 2 2 10 1 10 5 3 2 10 4 2 Sample Output Yes No |
建议先做 hdoj 3572
看到这道题,知道要离散化,也知道怎么将时间区间离散化,但不知道怎么处理建边。o(╯□╰)o 不得不ORZ神牛了
题意:有 N 个人来吃烤肉,每个人到达时间为 si,离开时间为 ei,点的烤肉数量为 ni,烤好一份肉所需时间为 ti。现在只有一台烧烤机,该机器每个单位时间能烤 M 份肉。问能否满足所有顾客的需求。
思路:先用数组rec记录所有si和ei,排序去重(离散化),保证区间不重叠。
把相邻时间区间虚拟成点,即把区间 [ rec[i], rec[i+1] ]当做一个点。
将每个人对时间点的建边处理变成对时间区间的建边处理。建好图,跑一次最大流判断是否满流即可。
建图:设置超级源点source,超级汇点sink
1,source到每个人i建边,容量为ni * ti;
2,相邻时间区间[ rec[i], rec[i+1] ] 到sink建边,容量为(rec[i+1] - rec[i]) * M,表示同时可以烤M个;
3,判断每个人的时间区间[si, ei]是否包含离散化后的相邻时间区间[ rec[i], rec[i+1] ]。若包含表示在该区间内可以提供足够的时间供给这个人烤肉,则建边容量无穷大,否则不建边。
AC代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define MAXN 800 #define MAXM 200000+10 #define INF 0x3f3f3f3f using namespace std; struct Edge { int from, to, cap, flow, next; }; Edge edge[MAXM]; int head[MAXN], edgenum, cur[MAXN]; int dist[MAXN]; bool vis[MAXN]; int N, M; void init() { edgenum = 0; memset(head, -1, sizeof(head)); } void addEdge(int u, int v, int w) { Edge E1 = {u, v, w, 0, head[u]}; edge[edgenum] = E1; head[u] = edgenum++; Edge E2 = {v, u, 0, 0, head[v]}; edge[edgenum] = E2; head[v] = edgenum++; } int sumflow;//记录源点传入的总流量 int source, sink;//超级源点 超级汇点 struct Node { int s, n, e, t; }; Node num[210]; int rec[500]; void getMap() { source = 0; int len = 1; sumflow = 0; for(int i = 1; i <= N; i++) { scanf("%d%d%d%d", &num[i].s, &num[i].n, &num[i].e, &num[i].t); addEdge(source, i, num[i].n * num[i].t); sumflow += num[i].n * num[i].t; rec[len++] = num[i].s; rec[len++] = num[i].e; } sort(rec+1, rec+len); //去重 int R = 2; for(int i = 2; i < len; i++)//滚动数组优化 if(rec[i] != rec[i-1]) rec[R++] = rec[i];//得到R-1个端点 sort(rec+1, rec+R); //R-1个端点 R-2个区间 sink = N+R-1;//超级汇点 for(int i = 1; i < R-1; i++)//对R-2个区间处理 addEdge(i+N, sink, (rec[i+1]-rec[i]) * M); for(int i = 1; i <= N; i++)//对每个人的用餐时间区间 处理 { for(int j = 1; j < R-1; j++)//枚举R-2个区间 { if(num[i].s <= rec[j] && num[i].e >= rec[j+1])//时间容纳区间 容量无穷大 addEdge(i, j+N, INF); } } } bool BFS(int s, int t) { queue<int> Q; memset(dist, -1, sizeof(dist)); memset(vis, false, sizeof(vis)); dist[s] = 0; vis[s] = true; Q.push(s); while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i = head[u]; i != -1; i = edge[i].next) { Edge E = edge[i]; if(!vis[E.to] && E.cap > E.flow) { dist[E.to] = dist[u] + 1; if(E.to == t) return true; vis[E.to] = true; Q.push(E.to); } } } return false; } int DFS(int x, int a, int t) { if(x == t || a == 0) return a; int flow = 0, f; for(int &i = cur[x]; i != -1; i = edge[i].next) { Edge &E = edge[i]; if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(a, E.cap - E.flow), t)) > 0) { edge[i].flow += f; edge[i^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } int Maxflow(int s, int t) { int flow = 0; while(BFS(s, t)) { memcpy(cur, head, sizeof(head)); flow += DFS(s, INF, t); } return flow; } int main() { while(scanf("%d%d", &N, &M) != EOF) { init(); getMap(); if(Maxflow(source, sink) == sumflow)//满流 printf("Yes\n"); else printf("No\n"); } return 0; }
kebabTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1273 Accepted Submission(s): 532 Problem Description Almost everyone likes kebabs nowadays (Here a kebab means pieces of meat grilled on a long thin stick). Have you, however, considered about the hardship of a kebab roaster while Now N customers is coming. Customer i will arrive at time si (which means the roaster cannot serve customer i until time si). He/She will order ni kebabs, each one of which requires a total amount of ti unit time to get it well-roasted, and want to get them Oh, I forgot to say that the roaster needs not to roast a single kebab in a successive period of time. That means he can divide the whole ti unit time into k (1<=k<=ti) parts such that any two adjacent parts don’t have to be successive in time. He can also Input There are multiple test cases. The first line of each case contains two positive integers N and M. N is the number of customers and M is the maximum kebabs the grill can roast There is a blank line after each input block. Restriction: 1 <= N <= 200, 1 <= M <= 1,000 1 <= ni, ti <= 50 1 <= si < ei <= 1,000,000 Output If the roaster can satisfy all the customers, output “Yes” (without quotes). Otherwise, output “No”. Sample Input 2 10 1 10 6 3 2 10 4 2 2 10 1 10 5 3 2 10 4 2 Sample Output Yes No |
版权声明:本文为博主原创文章,未经博主允许不得转载。