String problem

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=5772

Description

This is a simple problem about string. Now a string S contains only ‘0’-‘9’. ?? wants to select a subsequence from this string. And makes this subsequence score maximum. The subsequence’s score is calculated as follows:

Score= Value – Total_Cost

The calculation of the Cost is as follows:

If the number of characters x in the subsequence is kx, And the two coefficients are ax,bx,The cost of character x calculated as follows:

{cost[x]=0,kx=0cost[x]=ax∗(kx−1)+bx,kx≠0

TotalCost=∑i=09cost[i]

The calculation of the Value is as follows:

Value=0;

for(int i=1;i<=length(substr);++i){

for(int j=1;j<=length(substr);++j){

if(i!=j)

Value+=w[id[i]][id[j]];

}

}

id[i] is the position of the subsequence’s ith character in the original string,for example,if the original string is “13579”,and the subsubquence is “159”,then the array id ={1,3,5}. The w is a weight matrix.

Input

The first line contains an integer T, denoting the number of the test cases.

For each test case, the first line contains one integers n, the length of a string.

Next line contains the string S.

Next ten lines,each line contains ai,bi,denote the char i’s(0-9) coefficients

Next is a n*n matrix w.

Limits:

T<=20,

0<=n<=100

0<=ai<=bi<=1000

0<=w[i][j]<=50

Output

Each test output one line “Case #x: y” , where x is the case number ,staring from 1. y is the Maximum score.

Sample Input

1

3

135

1 2

1 2

1 2

1 2

1 2

1 2

1 2

1 2

1 2

1 2

0 0 3

1 0 0

4 0 0

Sample Output

Case #1: 3

Hint

we can choose “15”,id[]={1,3} then Value=w[1][3]+w[3][1]=7,

Total_Cost=2+2=4,Score=7-4=3

Hint

题意

给你一个字符串,只含有数字。

你需要选择出一个子序列,使得这个子序列的权值最大。

这个子序列如果这个数字第一次出现就ans-=bx,否则就-=ax

然后如果第i个字符和第j个字符都在子序列里面,那么ans+=w[i][j]

问你最大ans是多少

题解:

比较显然的就是最大闭合子图了,这个跑网络流就是了。

标准题解:

网络流:最大权闭合子图。

思路如下:

首先将点分为3类

第一类:Pij 表示第i个点和第j个点组合的点,那么Pij的权值等于w[i][j]+w[j][i](表示得分)

第二类:原串中的n个点每个点拆出一个点,第i个点权值为 –a[s[i]] (表示要花费)

第三类:对于10种字符拆出10个点,每个点的权值为 -(b[x]-a[x])

那么我们可以得到一个关系图 ,对于第一类中的点Pij,如果想要选择Pij,你就必须要选中第二类中的点i和j,对于第二类中的点如果你想选中第i个点,其对应的字符s[i],那么就必须选中第三类中s[i] 对应的点,因为每个种类的点第一次选中时花费是b[s[i]],而第二类中花费都是a[s[i]],一定要补上b[s[i]]-a[s[i]],而且只需要补上一次。

得到上面的关系图后然后就是普通的最大权闭合子图问题,直接求解即可。

但是我们队比较邪,我们先2^10枚举了一下,然后再跑的网络流,但是这样会TLE。

于是我们就XJB只搜了后面的几个状态和前面的状态,然后跑网络流就过了……

下面代码是我们队的谐星做法,非正解,正解按照前面的思路建图就好了。

另外这个图跑ISAP比跑dinic快的多。。。。

代码

  1. #include<bits/stdc++.h>
  2. #define Maxn 60009
  3. #define Maxm 400009
  4. #define inf 100000000
  5. #define LL int
  6. using namespace std;
  7. const int MAXN=100000,MAXM=100000;
  8. struct Edge
  9. {
  10. int v,c,f,nx;
  11. Edge() {}
  12. Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
  13. } E[MAXM];
  14. int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],N,sz;
  15. void init(int _n)
  16. {
  17. N=_n,sz=0; memset(G,-1,sizeof(G[0])*N);
  18. }
  19. void link(int u,int v,int c)
  20. {
  21. E[sz]=Edge(v,c,0,G[u]); G[u]=sz++;
  22. E[sz]=Edge(u,0,0,G[v]); G[v]=sz++;
  23. }
  24. int ISAP(int S,int T)
  25. {//S -> T
  26. int maxflow=0,aug=inf,flag=false,u,v;
  27. for (int i=0;i<N;++i)cur[i]=G[i],gap[i]=dis[i]=0;
  28. for (gap[S]=N,u=pre[S]=S;dis[S]<N;flag=false)
  29. {
  30. for (int &it=cur[u];~it;it=E[it].nx)
  31. {
  32. if (E[it].c>E[it].f&&dis[u]==dis[v=E[it].v]+1)
  33. {
  34. if (aug>E[it].c-E[it].f) aug=E[it].c-E[it].f;
  35. pre[v]=u,u=v; flag=true;
  36. if (u==T)
  37. {
  38. for (maxflow+=aug;u!=S;)
  39. {
  40. E[cur[u=pre[u]]].f+=aug;
  41. E[cur[u]^1].f-=aug;
  42. }
  43. aug=inf;
  44. }
  45. break;
  46. }
  47. }
  48. if (flag) continue;
  49. int mx=N;
  50. for (int it=G[u];~it;it=E[it].nx)
  51. {
  52. if (E[it].c>E[it].f&&dis[E[it].v]<mx)
  53. {
  54. mx=dis[E[it].v]; cur[u]=it;
  55. }
  56. }
  57. if ((--gap[dis[u]])==0) break;
  58. ++gap[dis[u]=mx+1]; u=pre[u];
  59. }
  60. return maxflow;
  61. }
  62. bool bfs(int S,int T)
  63. {
  64. static int Q[MAXN]; memset(dis,-1,sizeof(dis[0])*N);
  65. dis[S]=0; Q[0]=S;
  66. for (int h=0,t=1,u,v,it;h<t;++h)
  67. {
  68. for (u=Q[h],it=G[u];~it;it=E[it].nx)
  69. {
  70. if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
  71. {
  72. dis[v]=dis[u]+1; Q[t++]=v;
  73. }
  74. }
  75. }
  76. return dis[T]!=-1;
  77. }
  78. int dfs(int u,int T,int low)
  79. {
  80. if (u==T) return low;
  81. int ret=0,tmp,v;
  82. for (int &it=cur[u];~it&&ret<low;it=E[it].nx)
  83. {
  84. if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f)
  85. {
  86. if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
  87. {
  88. ret+=tmp; E[it].f+=tmp; E[it^1].f-=tmp;
  89. }
  90. }
  91. }
  92. if (!ret) dis[u]=-1; return ret;
  93. }
  94. int dinic(int S,int T)
  95. {
  96. int maxflow=0,tmp;
  97. while (bfs(S,T))
  98. {
  99. memcpy(cur,G,sizeof(G[0])*N);
  100. while (tmp=dfs(S,T,inf)) maxflow+=tmp;
  101. }
  102. return maxflow;
  103. }
  104. struct st
  105. {
  106. int u,v;
  107. LL value;
  108. }e[Maxm];
  109. int cost[MAXN];
  110. int mp[105][105];
  111. int a[10],b[10],nn;
  112. int Ans = 0;
  113. string s;
  114. LL get(int zt){
  115. vector<int> tmp;
  116. LL sum=0;
  117. int cccc = 0;
  118. for(int i=0;i<10;i++){
  119. if((1<<i)&zt){
  120. sum-=(b[i]-a[i]);
  121. }
  122. }
  123. for(int i=0;i<s.size();i++){
  124. int num = s[i]-'0';
  125. if((1<<num)&zt){
  126. tmp.push_back(i+1);
  127. cost[i+1]=a[s[i]-'0'];
  128. // cout<<i<<" ";
  129. }
  130. }
  131. int m = 1;
  132. for(int i=0;i<tmp.size();i++){
  133. for(int j=i+1;j<tmp.size();j++){
  134. e[m].u=tmp[i];
  135. e[m].v=tmp[j];
  136. e[m].value=mp[tmp[i]][tmp[j]]+mp[tmp[j]][tmp[i]];
  137. sum+=e[m].value;
  138. m++;
  139. }
  140. }
  141. if(sum<=Ans)return 0;
  142. m--;
  143. init(12000);
  144. int n = tmp.size();
  145. for(int i=1;i<=m;i++)
  146. {
  147. link(0,i,e[i].value);
  148. link(i,m+e[i].u,inf);
  149. link(i,m+e[i].v,inf);
  150. }
  151. for(int i=1;i<=n;i++)
  152. link(tmp[i-1]+m,m+nn+1,cost[tmp[i-1]]);
  153. LL ans=ISAP(0,m+nn+1);
  154. return sum-ans;
  155. }
  156. int cas = 0;
  157. int vvv[15];
  158. int ccc = 0;
  159. int times = 0 ;
  160. void dfs1(int x,int tmp,int k){
  161. if(x==10){
  162. if( (k>=ccc-7||ccc<=2) )Ans=max(Ans,get(tmp));
  163. return;
  164. }
  165. if(vvv[x])dfs1(x+1,tmp|(1<<x),k+1);
  166. dfs1(x+1,tmp,k);
  167. }
  168. void solve(){
  169. memset(vvv,0,sizeof(vvv));
  170. Ans=0;
  171. times=0;
  172. scanf("%d",&nn);
  173. cin>>s;
  174. ccc=0;
  175. for(int i=0;i<s.size();i++){
  176. if(vvv[s[i]-'0']==0)ccc++;
  177. vvv[s[i]-'0']=1;
  178. }
  179. for(int i=0;i<10;i++){
  180. scanf("%d%d",&a[i],&b[i]);
  181. }
  182. for(int i=1;i<=nn;i++){
  183. for(int j=1;j<=nn;j++){
  184. scanf("%d",&mp[i][j]);
  185. }
  186. }
  187. dfs1(0,0,0);
  188. cout<<"Case #"<<++cas<<": "<<Ans<<endl;
  189. }
  190. int main(){
  191. int t;
  192. scanf("%d",&t);
  193. while(t--)solve();
  194. return 0;
  195. }

hdu 5772 String problem 最大权闭合子图的更多相关文章

  1. hdu 3917 Road constructions 最大权闭合子图

    样例说明: n(城市数目)   m(工程队数目) 每个工程队上交的税收 val[i] k(k个工程) xi   yi  ci  costi , 工程队ci承包由xi到yi,政府的补贴为costi 注意 ...

  2. HDU5772 String problem 最大权闭合图+巧妙建图

    题意:自己看吧(不是很好说) 分析: 网络流:最大权闭合子图. 思路如下: 首先将点分为3类 第一类:Pij 表示第i个点和第j个点组合的点,那么Pij的权值等于w[i][j]+w[j][i](表示得 ...

  3. HDU 5772 String problem

    最大权闭合子图.建图巧妙. 最大权闭合子图: #pragma comment(linker, "/STACK:1024000000,1024000000") #include< ...

  4. HDU 3879 Base Station(最大权闭合子图)

    将第i个用户和他需要的基站连边,转化成求二分图的最大权闭合子图. 答案=正权点之和-最小割. # include <cstdio> # include <cstring> # ...

  5. hdu5772-String problem(最大权闭合子图问题)

    解析: 多校标答 第一类:Pij 表示第i个点和第j个点组合的点,那么Pij的权值等于w[i][j]+w[j][i](表示得分)第二类:原串中的n个点每个点拆出一个点,第i个点权值为 –a[s[i]] ...

  6. HDU5772 String problem(最大权闭合子图)

    题目..说了很多东西 官方题解是这么说的: 首先将点分为3类 第一类:Pij 表示第i个点和第j个点组合的点,那么Pij的权值等于w[i][j]+w[j][i](表示得分) 第二类:原串中的n个点每个 ...

  7. HDU4971 A simple brute force problem.(强连通分量缩点 + 最大权闭合子图)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4971 Description There's a company with several ...

  8. HDU 5855 Less Time, More profit 最大权闭合子图

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5855 Less Time, More profit Time Limit: 2000/1000 MS ...

  9. HDU 3879 Base Station(最大权闭合子图)

    经典例题,好像说可以转化成maxflow(n,n+m),暂时只可以勉强理解maxflow(n+m,n+m)的做法. 题意:输入n个点,m条边的无向图.点权为负,边权为正,点权为代价,边权为获益,输出最 ...

随机推荐

  1. bzoj千题计划222:bzoj2329: [HNOI2011]括号修复(fhq treap)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2329 需要改变的括号序列一定长这样 :)))((( 最少改变次数= 多余的‘)’/2 [上取整] + ...

  2. JS模块化写法(转)

    一.原始写法 模块就是实现特定功能的一组方法. 只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块. function m1(){ //... } function m2(){ // ...

  3. VirtualBox中CentOS遇到的问题

    centos7 安装步骤 https://www.cnblogs.com/hihtml5/p/8217062.html 静态ip设置 TYPE="Ethernet" PROXY_M ...

  4. 云计算--hbase shell

    具体的 HBase Shell 命令如下表 1.1-1 所示: 下面我们将以“一个学生成绩表”的例子来详细介绍常用的 HBase 命令及其使用方法. 这里 grad 对于表来说是一个列,course ...

  5. zabbix 3.2.2 server端(源码包)安装部署 (一)【转】

    环境准备: 操作系统 CentOS 6.8 2.6.32-642.11.1.el6.x86_64 zabbix server 172.16.10.150 zabbix agent 172.16.10. ...

  6. 内存溢出(Memory Overflow)和内存泄露(Memory Leak)的区别

    内存泄漏指你用malloc或new申请了一块内存,但是没有通过free或delete将内存释放,导致这块内存一直处于占用状态 内存溢出指你申请了10个字节的空间,但是你在这个空间写入11或以上字节的数 ...

  7. (windows下)安装mysql

    一.先从mysql的官网上下载对应版本的mysql zip包(适用于windows下的) 二.解压zip包放到自定义的文件夹下(我放的是e盘,路径为E:\mysql-5.6.40-winx64) 三. ...

  8. Python学习笔记:算法的重要性

    今日看了一个基础的教程<8分钟学会一个算法>,偶然间看到一个很简单的例子,仅当记录一下. 题目:已知a+b+c=1000,且a^2+b^2=c^2,求a,b,c的所有自然数解? #### ...

  9. ERP渠道文档管理(二十四)

    基本需求: 用例图: 存储过程: CREATE PROCEDURE [dbo].[BioErpCrmChannelDocument_ADD] @DocumentID int, @ChannelID i ...

  10. Hanoi Factorys

    题面 思路 这道题看似难的一匹,实际上也难的一批还好,甚至n^2 DP都有50分呢. 原谅我一失手成千古恨. 50分思路 就是sort后根据条件DP if (LIS[i].b>LIS[j].a) ...