TJOI2015题解

打算来做一波TJOI2015,来写题解啦!

Day1:

T1:

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3996

首先我们对题目中的式子化简一下,得到

于是这就成了一个最小割模型:

  • S和(i,j)连边,权值为b[i,j]
  • (i,j)和i,j分别连边,权值为inf
  • i和T连边,权值为c[i]

于是跑一下最小割就可以了;

(然而不知道发生了什么。。。最小割跑不过去。。。似乎bzoj把p党卡常数了QAQ)

(cyand神犇说他在省选的时候贪心了一发,就过了,至今找不出反例,于是我水过去了)

最小割代码如下:

  1 uses math;
  2 var s,t,n,i,j,tot,w,cnt:longint;
  3     last,pre,other,flow:array[0..2600000] of longint;
  4     l,q:array[0..3000000] of longint;
  5     ans:int64;
  6 procedure insert(a,b,c,d:longint);
  7 begin
  8   pre[tot]:=last[a];
  9   last[a]:=tot;
 10   other[tot]:=b;
 11   flow[tot]:=c;
 12   inc(tot);
 13   pre[tot]:=last[b];
 14   last[b]:=tot;
 15   other[tot]:=a;
 16   flow[tot]:=d;
 17   inc(tot);
 18 end;
 19 function bfs:boolean;
 20 var s1,t1,u,v,q1:longint;
 21 begin
 22   fillchar(q,sizeof(q),0);
 23   for i:=0 to n do
 24     l[i]:=-1;
 25   s1:=0;
 26   t1:=1;
 27   l[s]:=1;
 28   q[t1]:=s;
 29   while (s1<t1) do
 30   begin
 31     inc(s1);
 32     u:=q[s1];
 33     q1:=last[u];
 34     while (q1>=0) do
 35     begin
 36       v:=other[q1];
 37       if (flow[q1]>0) and (l[v]=-1) then
 38       begin
 39         inc(t1);
 40         q[t1]:=v;
 41         l[v]:=l[u]+1;
 42       end;
 43       q1:=pre[q1];
 44     end;
 45   end;
 46   if (l[t]=-1) then exit(false) else exit(true);
 47 end;
 48 function find(u,int:longint):longint;
 49 var w,v,q1,t1:longint;
 50 begin
 51   if (u=t) then exit(int);
 52   w:=0;
 53   q1:=last[u];
 54   while (q1>=0) and (w<int) do
 55   begin
 56     v:=other[q1];
 57     if (l[v]=l[u]+1) then
 58     begin
 59       t1:=find(v,min(flow[q1],int-w));
 60       flow[q1]:=flow[q1]-t1;
 61       flow[q1 xor 1]:=flow[q1 xor 1]+t1;
 62       w:=w+t1;
 63     end;
 64     q1:=pre[q1];
 65   end;
 66   if (w>=int) then l[u]:=-1;
 67   exit(w);
 68 end;
 69 function dinic:int64;
 70 var e:longint;
 71   ans:int64;
 72 begin
 73   ans:=0;
 74   while bfs do
 75   begin
 76     e:=find(s,maxlongint);
 77     ans:=ans+e;
 78   end;
 79   exit(ans);
 80 end;
 81 begin
 82   readln(n);
 83   s:=n*n+n+1;
 84   t:=n*n+n+2;
 85   tot:=0;
 86   for i:=0 to t do
 87     last[i]:=-1;
 88   cnt:=n;
 89   ans:=0;
 90   for i:=1 to n do
 91   begin
 92     for j:=1 to n do
 93     begin
 94       read(w);
 95       inc(cnt);
 96       insert(s,cnt,w,0);
 97       insert(cnt,i,maxlongint,0);
 98       if (i<>j) then insert(cnt,j,maxlongint,0);
 99       ans:=ans+w;
100     end;
101     readln;
102   end;
103   for i:=1 to n do
104   begin
105     read(w);
106     insert(i,t,w,0);
107   end;
108   readln;
109   n:=t;
110   writeln(ans-dinic);
111 end.
112   

贪心代码如下:

 1 var n,i,j,s,ans,max,max1:longint;
 2     b:array[0..1000,0..1000] of longint;
 3     c,inc:array[0..1000] of longint;
 4 begin
 5   readln(n);
 6   for i:=1 to n do
 7   begin
 8     for j:=1 to n do
 9         read(b[i,j]);
10     readln;
11   end;
12   for i:=1 to n do
13     read(c[i]);
14   readln;
15   fillchar(inc,sizeof(inc),0);
16   s:=0;
17   ans:=0;
18   for i:=1 to n do
19   begin
20     s:=0;
21     for j:=1 to n do
22         s:=s+b[i,j]+b[j,i];
23     inc[i]:=b[i,i]-s+c[i];
24   end;
25   for i:=1 to n do
26     for j:=1 to n do
27         ans:=ans+b[i,j];
28   for i:=1 to n do
29     ans:=ans-c[i];
30   while true do
31   begin
32     max:=-1;
33     max1:=-1;
34     for i:=1 to n do
35       if (max<inc[i]) then
36       begin
37         max:=inc[i];
38         max1:=i;
39       end;
40     if (max1=-1) then break;
41     ans:=ans+max;
42     for i:=1 to n do
43       inc[i]:=inc[i]+b[i,max1]+b[max1,i];
44     inc[max1]:=-1;
45   end;
46   writeln(ans);
47 end.
48     

T2:

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3997

本题要用一个Dilworth定理:DAG最小链覆盖=最大独立子集,

于是发现最大独立子集显然符合题目,于是直接跑DP就可以了,方程如下:

f[i,j]=max{f[i-1,j+1]+a[i,j],f[i-1,j],f[i,j+1]}

代码如下:

 1 var t,l,n,m,i,j:longint;
 2     a,f:array[0..1005,0..1005] of int64;
 3 begin
 4   readln(t);
 5   for l:=1 to t do
 6   begin
 7     readln(n,m);
 8     fillchar(a,sizeof(a),0);
 9     fillchar(f,sizeof(f),0);
10     for i:=1 to n do
11     begin
12       for j:=1 to m do
13         read(a[i,j]);
14       readln;
15     end;
16     for i:=1 to n do
17         for j:=m downto 1 do
18         begin
19           f[i,j]:=f[i-1,j+1]+a[i,j];
20           if (f[i-1,j]>f[i,j]) then f[i,j]:=f[i-1,j];
21           if (f[i,j+1]>f[i,j]) then f[i,j]:=f[i,j+1];
22         end;
23     writeln(f[n,1]);
24   end;
25 end.
时间: 2024-10-13 11:38:16

TJOI2015题解的相关文章

[TJOI2015]弦论 题解(第k小子串)

题意: 对于一个给定的长度为n的字符串,求出它的第k小子串. 有参数t,t为0则表示不同位置的相同子串算作一个,t为1则表示不同位置的相同子串算作多个. 题解: 首先,因为t的原因,后缀数组较难实现,这里不讨论. 使用后缀自动机: 因为,这里需要按字典序考虑子串,所以要使用trs指针. 首先,计算出每个子串的贡献:t=0则为1,t=1则为出现次数. 然后,通过记搜算出匹配到每个点之后可以形成多少贡献.因为使用trs,无需考虑压缩. 最后,在每个节点处找到唯一一个应当向下计算的点,循环直到找到解.

【BZOJ】【TJOI2015】线性代数

网络流/最小割/最大权闭合图 2333好开心,除了一开始把$500^2$算成25000……导致数组没开够RE了一发,可以算是一次AC~ 咳咳还是回归正题来说题解吧: 一拿到这道题,我就想:这是什么鬼玩意……矩阵乘法早忘了……画了半天也想不起来到底是谁乘谁,只记得有个式子:$c[i][j]=\sum a[i][k]*b[k][j]$ 好吧没关系,既然画图不行了,我们就先拿这个东西,纯代数来搞! D的表达式,里面那层我们可以写成:$\sum a[i][k]*b[k][j] - c[i][j]$ 然而

bzoj 3998: [TJOI2015]弦论(后缀自动机)

题目链接:bzoj 3998: [TJOI2015]弦论 题意: 对于一个给定长度为N的字符串,求它的第K小子串是什么. 题解: 后缀自动机O(n)*26解决. 对于op=0,num[i]=1,对于op=1,num[i]=cnt[i]. 因为cnt[i](即right集)表示以i节点结尾的后缀出现的次数. 1 #include<cstdio> 2 #include<cstring> 3 #define F(i,a,b) for(int i=a;i<=b;++i) 4 #def

bzoj 3997: [TJOI2015]组合数学

3997: [TJOI2015]组合数学 Description 给出一个网格图,其中某些格子有财宝,每次从左上角出发,只能向下或右走.问至少走多少次才能将财宝捡完.此对此问题变形,假设每个格子中有好多财宝,而每一次经过一个格子至多只能捡走一块财宝,至少走多少次才能把财宝全部捡完. Input 第一行为正整数T,代表数据组数. 每组数据第一行为正整数N,M代表网格图有N行M列,接下来N行每行M个非负整数,表示此格子中财宝数量,0代表没有 Output 输出一个整数,表示至少要走多少次. Samp

【BZOJ3997】[TJOI2015]组合数学 最长反链

[BZOJ3997][TJOI2015]组合数学 Description 给出一个网格图,其中某些格子有财宝,每次从左上角出发,只能向下或右走.问至少走多少次才能将财宝捡完.此对此问题变形,假设每个格子中有好多财宝,而每一次经过一个格子至多只能捡走一块财宝,至少走多少次才能把财宝全部捡完. Input 第一行为正整数T,代表数据组数. 每组数据第一行为正整数N,M代表网格图有N行M列,接下来N行每行M个非负整数,表示此格子中财宝数量,0代表没有 Output 输出一个整数,表示至少要走多少次.

【BZOJ3998】[TJOI2015]弦论 后缀自动机

[BZOJ3998][TJOI2015]弦论 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个.T=1则表示不同位置的相同子串算作多个.K的意义如题所述. Output 输出仅一行,为一个数字串,为第K小的子串.如果子串数目不足K个,则输出-1 Sample Input aabc 0 3 Sample Output aab HINT N<=5*10

4001: [TJOI2015]概率论

4001: [TJOI2015]概率论 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 262  Solved: 108[Submit][Status][Discuss] Description Input 输入一个正整数N,代表有根树的结点数 Output 输出这棵树期望的叶子节点数.要求误差小于1e-9 Sample Input 1 Sample Output 1.000000000 HINT 1<=N<=10^9 Source 题解:首先给

洛谷 P1079 Vigen&#232;re 密码 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1079 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为 南军所广泛使用. 在密码学中,我们称需要加密的信息为明文,用 M 表示:称加密后的信息为密文,用 C 表示:而密钥是一种

8.8联考题解

今天的T1让我怀疑我是不是在做奥赛题--这考的是什么知识点啊这个,会不会用绝对值函数? Evensgn 的债务 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Evensgn 有一群好朋友,他们经常互相借钱.假如说有三个好朋友A,B,C.A 欠 B 20 元,B 欠 C 20 元,总债务规模为 20+20=40 元.Evensgn 是个追求简约的人,他觉得这样的债务太繁杂了.他认为,上面的债务可以完全等价为 A 欠C20 元,B 既不欠别人,别人也不欠他.这样总债务规模就压缩到了