COJ 0501 取数游戏(TPM)
| 取数游戏(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)的更多相关文章
- NOIP2007 矩阵取数游戏
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
- 1166 矩阵取数游戏[区间dp+高精度]
1166 矩阵取数游戏 2007年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description [ ...
- 矩阵取数游戏 NOIP 2007
2016-05-31 17:26:45 题目链接: NOIP 2007 矩阵取数游戏(Codevs) 题目大意: 给定一个矩阵,每次在每一行的行首或者行尾取一个数乘上2^次数,求取完最多获得的分数 解 ...
- 洛谷 P1005 矩阵取数游戏
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
- BZOJ1978: [BeiJing2010]取数游戏 game
1978: [BeiJing2010]取数游戏 game Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 650 Solved: 400[Submit] ...
- codevs1166 矩阵取数游戏
题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均 为非负整数.游戏规则如下: 1. 每次取数时须从每行各取走一个 ...
- 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 -- ...
- 矩阵取数游戏洛谷p1005
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
- 计蒜客 取数游戏 博弈+dp
题目链接 取数游戏 思路:dp(x, y)表示先手在区间[x, y]能取得的最大分数.当先手取完,就轮到后手去,后手一定会选择当前能令他得到最大分数的策略,其实当先手在[x, y]区间两端取走一个数, ...
随机推荐
- Linux 监控CPU 温度
安装测试系统: 硬件:普通PC机, 软件:redhat linux as 4 2.6 .9 , 安装系统自带的lm_sensors-2.8.7-2.i386 你也可以从[url]http://w ...
- Java8特性详解 lambda表达式 Stream
1.lambda表达式 Java8最值得学习的特性就是Lambda表达式和Stream API,如果有python或者javascript的语言基础,对理解Lambda表达式有很大帮助,因为Java正 ...
- 免写前缀JS包--prefixfree.min.js--插件
/** * StyleFix 1.0.3 & PrefixFree 1.0.7 * @author Lea Verou * MIT license */ (function(){functio ...
- Mysql 列转行group_concat函数,与行转列
1.正常情况. SELECT JoinEventIds from nt_mainnum 2.使用group_concat函数 select group_concat(JoinEventIds) fro ...
- Android打开系统的Document文档图片选择
打开Document UI 过滤图片 private void startAcitivty() { Intent intent = new Intent(); intent.setAction(&qu ...
- Android开发手记(16) 数据存储一 SharedPreferences
Android为数据存储提供了五种方式: 1.SharedPreferences 2.文件存储 3.SQLite数据库 4.ContentProvider 5.网络存储 SharedPreferenc ...
- Binary XML file : Error inflating class com.esri.android.map.MapView
在测试esri arcgis for android的第一个程序Helloworld的时候,报这样的错: Binary XML file : Error inflating class com.esr ...
- 《C# 并发编程 · 经典实例》读书笔记
前言 最近在看<C# 并发编程 · 经典实例>这本书,这不是一本理论书,反而这是一本主要讲述怎么样更好的使用好目前 C#.NET 为我们提供的这些 API 的一本书,书中绝大部分是一些实例 ...
- [转]Delphi 快捷键 让你更像高手!!
新一篇: IDFTP 控件使用 >>代码模板 : CTRL+J >>代码整块移动 : CTRL+SHIFT+I(右移) CTRL+SHIFT+U(左移)>>选中窗体 ...
- ExtJs API 下载以及部署
ExtJs API 下载方法 1.进入sencha官网:https://www.sencha.com/ 2.点击“Docs”进入文档帮助页面:http://docs.sencha.com/ 3.点击左 ...