取数游戏(TPM)
难度级别:D; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
试题描述

给你一个n*n的格子的棋盘,每个格子里面有一个非负数。从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能有公共边,并且取出的数的和最大。(二分图匹配练习)

输入
第一行是一个正整数n (n<20)。
接下来是 n*n 个非负数。
输出
输出可能取得的最大的和。
输入示例
3
5 9 4
8 3 6
2 7 1
输出示例
30
其他说明
n<20

题解:“没有公共边”这是赤裸裸的二分图呀!随便按(i+j)&1造个二分图跑了就行。。。

而且,这是我第一个接触的构造题吧= = 还是非常有纪念意义的= =我记得当年还是小健建给我亲自敲了一遍DInic然后敲了一遍这道题。。。回忆满满呢~

现在老练的ISAP+缩行:

 //这两道题有什么区别。。。= =
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=+,maxm=+,inf=-1u>>;
struct ISAP{
struct tedge{int x,y,w,next;}adj[maxm];int ms,fch[maxn];
int d[maxn],s[maxn],cur[maxn],gap[maxn],n,top;
void init(int n){
this->n=n;ms=;top=;
memset(d,-,sizeof(d));
memset(fch,-,sizeof(fch));
return;
}
void addedge(int u,int v,int w){
adj[ms]=(tedge){u,v,w,fch[u]};fch[u]=ms++;
adj[ms]=(tedge){v,u,,fch[v]};fch[v]=ms++;
return;
}
void bfs(){
queue<int>Q;Q.push(n);d[n]=;
while(!Q.empty()){
int u=Q.front();Q.pop();
for(int i=fch[u];i!=-;i=adj[i].next){
int v=adj[i].y;
if(d[v]==-) d[v]=d[u]+,Q.push(v);
}
} return;
}
int maxflow(int S,int T){
n=T;bfs();int k=S,i,flow=;
for(i=;i<=n;i++) cur[i]=fch[i],gap[d[i]]++;
while(d[S]<n){
if(k==n){
int mi=inf,pos;
for(i=;i<top;i++) if(adj[s[i]].w<mi) mi=adj[s[i]].w,pos=i;
for(i=;i<top;i++) adj[s[i]].w-=mi,adj[s[i]^].w+=mi;
flow+=mi;top=pos;k=adj[s[top]].x;
}
for(i=cur[k];i!=-;i=adj[i].next){
int v=adj[i].y;
if(adj[i].w&&d[k]==d[v]+){cur[k]=i;k=v;s[top++]=i;break;}
}
if(i==-){
int lim=n;
for(i=fch[k];i!=-;i=adj[i].next){
int v=adj[i].y;
if(adj[i].w&&d[v]<lim) lim=d[v],cur[k]=i;
} if(--gap[d[k]]==) break;
d[k]=lim+;gap[d[k]]++;
if(k!=S) k=adj[s[--top]].x;
}
} return flow;
}
}sol;
inline int read(){
int x=,sig=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') sig=-;ch=getchar();}
while(isdigit(ch)) x=*x+ch-'',ch=getchar();
return x*=sig;
}
inline void write(int x){
if(x==){putchar('');return;}if(x<) putchar('-'),x=-x;
int len=,buf[];while(x) buf[len++]=x%,x/=;
for(int i=len-;i>=;i--) putchar(buf[i]+'');return;
}
int A[][],mx[]={,-,,},my[]={,,-,};
void init(){
int n=read();long long ans=;
sol.init(n*n+);int S=n*n+,T=n*n+;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
A[i][j]=read();
if((i+j)&){
sol.addedge(S,i*n+j-n,A[i][j]);
for(int d=;d<;d++){
int nx=i+mx[d],ny=j+my[d];
if(nx>=&&nx<=n&&ny>=&&ny<=n) sol.addedge(i*n+j-n,nx*n+ny-n,inf);
}
}
else sol.addedge(i*n+j-n,T,A[i][j]);
ans+=A[i][j];
}
write(ans-sol.maxflow(S,T));
return;
}
void work(){
return;
}
void print(){
return;
}
int main(){
init();work();print();return ;
}

当时最稚嫩的代码。。。真的有种说不出的感动:

 #include <iostream>
#include <queue>
using namespace std; const int maxn = + ;
const int maxm = + ; struct Edge
{
int from, to, cap, flow;
}; struct Dinic
{
int n, m, s, t;
int first[maxn], next[maxm]; Edge edges[maxm]; void init(int n)
{
this -> n = n;
m = ; memset(first, -, sizeof(first)); return ;
} void AddEdge(int from, int to, int cap)
{
edges[m] = (Edge){from, to, cap, };
next[m] = first[from];
first[from] = m++; edges[m] = (Edge){to, from, , };
next[m] = first[to];
first[to] = m++; return ;
} int d[maxn], cur[maxn];
bool vis[maxn]; int BFS()
{
memset(vis, , sizeof(vis));
queue<int> Q; Q.push(s);
vis[s] = true;
d[s] = ; while(!Q.empty())
{
int x = Q.front(); Q.pop(); for(int i = first[x]; i != -; i = next[i])
{
Edge& e = edges[i];
if(!vis[e.to] && e.cap > e.flow)
{
vis[e.to] = true;
d[e.to] = d[x] + ;
Q.push(e.to);
}
}
} return vis[t];
}
int DFS(int x, int a)
{
if(x == t || !a) return a; int f, flow = ; for(int& i = cur[x]; i != -; i = next[i])
{
Edge& e = edges[i];
if(d[e.to] == d[x] + && (f = DFS(e.to, min(a, e.cap - e.flow))) > )
{
flow += f;
a -= f;
e.flow += f;
edges[i ^ ].flow -= f;
if(!a) break;
}
}
return flow;
} int MaxFlow(int s, int t)
{
this -> s = s;
this -> t = t; int flow = ; while(BFS())
{
for(int i = ; i < n; i++) cur[i] = first[i];
flow += DFS(s, );
}
return flow; //你大爷!!!!!!!!!!!!!!!!
}
}sol; int a[][];
int nx[] = {, , -, };
int ny[] = {-, , , }; int main()
{
int n, m;
scanf("%d", &n); m = n; sol.init(n * m + ); long long double tot = ; int s = n * m;
int t = n * m + ; for(int i = ; i < n; i++)
for(int j = ; j < m; j++)
{
scanf("%d", &a[i][j]);
tot += a[i][j];
if((i + j) & )
{
sol.AddEdge(s, i * m + j, a[i][j]); for(int d = ; d < ; d++)
{
int mx = nx[d] + i;
int my = ny[d] + j; if(mx >= && mx < n && my >= && my < m)
{
sol.AddEdge(i * m + j, mx * m + my, );
}
}
}
else sol.AddEdge(i * m + j, t, a[i][j]);
} printf("%d\n", tot - sol.MaxFlow(s, t));
//system("pause");
return ;
}

搜索

复制

COJ 0501 取数游戏(TPM)的更多相关文章

  1. NOIP2007 矩阵取数游戏

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

  2. 1166 矩阵取数游戏[区间dp+高精度]

    1166 矩阵取数游戏 2007年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description [ ...

  3. 矩阵取数游戏 NOIP 2007

    2016-05-31 17:26:45 题目链接: NOIP 2007 矩阵取数游戏(Codevs) 题目大意: 给定一个矩阵,每次在每一行的行首或者行尾取一个数乘上2^次数,求取完最多获得的分数 解 ...

  4. 洛谷 P1005 矩阵取数游戏

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

  5. BZOJ1978: [BeiJing2010]取数游戏 game

    1978: [BeiJing2010]取数游戏 game Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 650  Solved: 400[Submit] ...

  6. codevs1166 矩阵取数游戏

    题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均 为非负整数.游戏规则如下: 1. 每次取数时须从每行各取走一个 ...

  7. BZOJ 1978: [BeiJing2010]取数游戏 game( dp )

    dp(x)表示前x个的最大值,  Max(x)表示含有因数x的dp最大值. 然后对第x个数a[x], 分解质因数然后dp(x) = max{Max(t)} + 1, t是x的因数且t>=L -- ...

  8. 矩阵取数游戏洛谷p1005

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

  9. 计蒜客 取数游戏 博弈+dp

    题目链接 取数游戏 思路:dp(x, y)表示先手在区间[x, y]能取得的最大分数.当先手取完,就轮到后手去,后手一定会选择当前能令他得到最大分数的策略,其实当先手在[x, y]区间两端取走一个数, ...

随机推荐

  1. [io PWA] keynote: Launching a Progressive Web App on Google.com

    Mainly about Material design (effects / colors / flashy stuff) Components (web components / polymer) ...

  2. XTU OJ 1210 Happy Number (暴力+打表)

    Problem Description Recently, Mr. Xie learn the concept of happy number. A happy number is a number ...

  3. hook研究结果备忘

    hook研究结果: 最近一周时间仔细研究了一下hook,也许不能称之为研究吧.顶多是让别人的思想拿过来抄袭一遍而已,写点结果也算对得起自己的这几天的苦心了. 1,首先从同事旁边听到了hook,然后看的 ...

  4. Java多态性举例说明

    Java多态性的概念也可以被说成“一个接口,多个方法”. (一)相关类 class A ...{ public String show(D obj)...{ return ("A and D ...

  5. Android(java)学习笔记222:开发一个多界面的应用程序之不同界面间互相传递数据(短信助手案例的优化:请求码和结果码)

    1.开启界面获取返回值 (1)采用一种特殊的方式开启Activity:               startActivityForResult(intent , 0): (2)在被开启的Activi ...

  6. java.util.Date和java.sql.Date

    java.util.Date是在除了SQL语句的情况下面使用的. java.sql.Date是针对SQL语句使用的,它只包含日期而没有时间部分 它们都有getTime方法返回毫秒数,自然就可以直接构建 ...

  7. BestCoder冠军赛 - 1009 Exploration 【Tarjan+并查集缩点】

    [题意] 给一个图,这个图中既有有向边,又有无向边,每条边只能走一次,问图中是否存在环. 最多10^6个点,10^6个无向边,10^6个有向边 [题解] 因为既有有向边又有无向边,所以不能单纯的用ta ...

  8. HDU5308-脑补-对拍

    先贴上对拍的结果: 感想:可以明显发现下标相差1的关系,所以对付这种需要大量脑补的水题,真的蛋疼,以前没用过对拍,只知道有这么回事,调程序什么的都是手算,人工模拟(经常大脑发热,严重缺氧不足),所以试 ...

  9. OpenXmlSdk导出Excel

    感觉OpenXmlSdk的语法真的不是很友好.研究了半天,只实现了简单的导出功能.对于单元格样式的设置暂时还是搞明白,网上的资料真的很少,官方文档是英文的.中文的文章大都是用工具(Open XML S ...

  10. project facet java version 1.6 is not supported

    可能你用的jdk1.5的包,而开发是用的jdk1.6,不允许1.5进行安装 法1,选中项目 Properties , 选择 Project Facets,右击选择 Java , Change Vers ...