Chess
Accepts: 1805
Submissions: 5738
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
思路:
一看到题目就是类似八皇后的水题...敲完直接提交TLE。顿时冷静一看被骗了,其实就是从max(n, m)中选min(n, m)的组合数,即C(min(n, m), max(n, m));
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const LL mod = 1e9+7;
LL C[1005][1005];
void init()
{
for(int i = 0; i <= 1000; ++i)
C[i][0] = 1;
for(int i = 1; i <= 1000; ++i)
for(int j = 1; j <= i; ++j)
C[i][j] = (C[i-1][j]+C[i-1][j-1])%mod;
}
int n, m;
int main()
{
int t; init();
scanf("%d", &t);
while(t--)
{
scanf("%d %d", &n, &m);
int minn = min(n, m);
int maxx = max(n, m);
printf("%I64d\n", C[maxx][minn]);
}
return 0;
}
度度熊的交易计划
Accepts: 460
Submissions: 2329
Time Limit: 12000/6000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
思路:
很明显的最小费用可行流,建图也挺好建,即新建立一个源点s和汇点t,源点s与每个片区建边,容量为该片区可生产个数,费用为单个成本,然后对所有片区之间建双向边容量为inf,费用为距离,之后再将每个片区与汇点t建边,容量为可卖出个数,费用为负的单价,最后跑一边最小费用流,并将最小费用取负当作答案。
不过还差最关键一步(比赛时没时间改了...),因为我们SPFA寻找的是当前残留网络的一条可改进路,我们是为了最小费用可行流,而非最大流,所以当我们寻找到从s到t的可改进路dis[t] > 0时,此可改进路不会再减少费用,所以需要把最小费用最大流寻找增广路时return的条件改为判断dis[t]是否大于0,ok...
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int maxn = 505;
const int maxm = 1e6+maxn*10;
struct node
{
int v, to, next;
LL w, cost;
}edge[maxm];
int no, n, m, s, t;
int head[maxn], vis[maxn], pre[maxn], rec[maxn];
LL dis[maxn];
queue<int> q;
inline void init()
{
no = 0;
memset(head, -1, sizeof head);
}
inline void add(int u, int v, LL w, LL f)
{
edge[no].v = v; edge[no].w = w; edge[no].cost = f;
edge[no].next = head[u]; head[u] = no++;
edge[no].v = u; edge[no].w = 0; edge[no].cost = -f;
edge[no].next = head[v]; head[v] = no++;
}
int SPFA(int s, int t)
{
memset(dis, 0x3f3f, sizeof dis);
memset(vis, 0, sizeof vis);
while(!q.empty()) q.pop();
q.push(s); dis[s] = 0; vis[s] = 1;
while(!q.empty())
{
int tp = q.front(); q.pop();
vis[tp] = 0;
int k = head[tp];
while(k != -1)
{
if(dis[edge[k].v] > dis[tp] + edge[k].cost && edge[k].w)
{
dis[edge[k].v] = dis[tp] + edge[k].cost;
pre[edge[k].v] = tp; rec[edge[k].v] = k;
if(vis[edge[k].v] == 0)
{
vis[edge[k].v] = 1;
q.push(edge[k].v);
}
}
k = edge[k].next;
}
}
if(dis[t] > 0) return 0;
return 1;
}
LL Mcmf(int s, int t)
{
LL minflow, mincost = 0, maxflow = 0;
int k;
while(SPFA(s, t))
{
k = t; minflow = inf;
while(k != s)
{
minflow = min(minflow, edge[rec[k]].w);
k = pre[k];
}
k = t; maxflow += minflow;
while(k != s)
{
mincost += minflow*edge[rec[k]].cost;
edge[rec[k]].w -= minflow;
edge[rec[k]^1].w += minflow;
k = pre[k];
}
}
return -mincost;
}
int main()
{
int a, b, c, d, s, t;
while(~scanf("%d %d", &n, &m))
{
init();
int s = 501, t = 502;
for(int i = 1; i <= n; ++i)
{
scanf("%d %d %d %d", &a, &b, &c, &d);
add(s, i, b, a);
add(i, t, d, -c);
}
for(int i = 1; i <= m; ++i)
{
scanf("%d %d %d", &a, &b, &c);
if(a == b) continue;
add(a, b, inf, c);
add(b, a, inf, c);
}
printf("%I64d\n", Mcmf(s, t));
}
return 0;
}
小小粉丝度度熊
Accepts: 1075
Submissions: 5191
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
思路:
先将所有能合成的区间合成一个,然后再从新的区间数组里进行尺取即可,注意细节(少写一个q++连TLE几发...)
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 1e5+5;
struct node
{
LL l, r;
bool operator<(const node k)const
{
return l < k.l;
}
} old[maxn], now[maxn];
int n, m, cnt;
LL ans, sum, at;
int main()
{
while(~scanf("%d %d", &n, &m))
{
for(int i = 1; i <= n; ++i)
scanf("%lld %lld", &old[i].l, &old[i].r);
sort(old+1, old+n+1);
cnt = 1;
now[cnt].l = old[1].l, now[cnt].r = old[1].r;
for(int i = 2; i <= n; ++i)
{
if(old[i].l <= now[cnt].r)
now[cnt].r = max(now[cnt].r, old[i].r);
else
{
++cnt;
now[cnt].l = old[i].l, now[cnt].r = old[i].r;
}
}
int q = 1, h = 2;
sum = now[1].r-now[1].l+1;
ans = sum+m, at = m;
while(h <= cnt)
{
LL jg = now[h].l-now[h-1].r-1;
if(at < jg)
{
++q;
while(q < h && at < jg)
{
LL jg1 = now[q].l-now[q-1].r-1;
sum -= now[q-1].r-now[q-1].l+1;
sum -= jg1, at += jg1;
++q;
}
if(at < jg)
{
ans = max(ans, now[h].r-now[h].l+1+at);
sum = now[h].r-now[h].l+1;
}
else
{
--q;
at -= jg, sum += jg;
sum += now[h].r-now[h].l+1;
ans = max(ans, sum+at);
}
}
else
{
at -= jg, sum += jg;
sum += now[h].r-now[h].l+1;
ans = max(ans, sum+at);
}
++h;
}
printf("%lld\n", ans);
}
return 0;
}
继续加油~