|
題意:給你一個n*m的方陣,每個方陣可以放石頭,每個格子放石頭需要花費,對於一個格子,如果放了石頭,或者它周圍的格子都放了石頭,則它將帶來收益。。。問,怎樣放石頭,使得收益-花費的值最大
分析:類似這樣的題做得挺多,看完不久,便想到可能是最小割的應用,然後就是長久的掙扎,下面就說說別人的構圖吧,我自己還沒完全明白= = 看了很多人的程式碼,就下面這個構圖簡單,而且明白一點點
首先將所有格子黑白塗色,將每個格子分成兩個節點,然後虛擬源點S和匯點T,對於黑色格子i,建兩條邊,S到i,容量為花費,i到i’容量為收益,對於白色格子j,也是兩條邊,j到T,容量為花費,j’到j容量為收益,對於i與j相鄰的,也建立兩條邊,i到j’,和i’到j,容量都是無窮,這樣做最大流,答案就是所有收益-最大流的值
仔細推敲了下,這個模型是假設取了所有格子的收益,然後怎樣擺放石子,使得花費最小,也就是這個模型就是求最小花費的,中間兩條容量為收益的邊正好限制花費不超過收益,在這個前提下,使得總花費最小,這就是我大概的理解
希望有誰會這道題,指導我下
PS:由於比賽時做完一題就剩20分鐘,弱菜無力。。。看完這題就剩6分鐘了,立馬貼了個模板,隨便構圖,最後樣例都調不出來,本來後悔不應該中途放鬆的,比賽後才發現就算做了我也做不出來,這題不是簡單題 T_T
冥思苦想了兩天,還是沒想出怎樣構圖,無奈看了別人的程式碼,還是懵懵懂懂,不過這回ID變黃了,貼下來當紀念吧,嘿嘿
程式碼:
// BEGIN CUT HERE
// END CUT HERE
#line 5 "SurroundingGame.cpp"
#include<cstdlib>
#include<cctype>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<sstream>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<fstream>
#include<numeric>
#include<iomanip>
#include<bitset>
#include<list>
#include<stdexcept>
#include<functional>
#include<utility>
#include<ctime>
using namespace std;
#define PB push_back
#define MP make_pair
#define REP(i,n) for(i=0;i<(n); i)
#define FOR(i,l,h) for(i=(l);i<=(h); i)
#define FORD(i,h,l) for(i=(h);i>=(l);--i)
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<double> VD;
typedef long long LL;
typedef pair<int,int> PII;
const int mm=1000000;
const int mn=22222;
const int oo=1000000000;
int node,src,dest,edge;
int reach[mm],flow[mm],next[mm];
int head[mn],work[mn],dis[mn],q[mn];
inline int min(int a,int b)
{
return a<b?a:b;
}
inline void prepare(int _node,int _src,int _dest)
{
node=_node,src=_src,dest=_dest;
for(int i=0;i<node; i)head[i]=-1;
edge=0;
}
inline void addedge(int u,int v,int c)
{
reach[edge]=v,flow[edge]=c,next[edge]=head[u],head[u]=edge ;
reach[edge]=u,flow[edge]=0,next[edge]=head[v],head[v]=edge ;
}
bool Dinic_bfs()
{
int i,u,v,l,r=0;
for(i=0;i<node; i)dis[i]=-1;
dis[q[r ]=src]=0;
for(l=0;l<r; l)
for(i=head[u=q[l]];i>=0;i=next[i])
if(flow[i]&&dis[v=reach[i]]<0)
{
dis[q[r ]=v]=dis[u] 1;
if(v==dest)return 1;
}
return 0;
}
int Dinic_dfs(int u,int exp)
{
if(u==dest)return exp;
for(int &i=work[u],v,tmp;i>=0;i=next[i])
if(flow[i]&&dis[v=reach[i]]==dis[u] 1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
{
flow[i]-=tmp;
flow[i^1] =tmp;
return tmp;
}
return 0;
}
int Dinic_flow()
{
int i,ret=0,delta;
while(Dinic_bfs())
{
for(i=0;i<node; i)work[i]=head[i];
while(delta=Dinic_dfs(src,oo))ret =delta;
}
return ret;
}
int get(char a)
{
if(a>='0'&&a<='9')return a-'0';
if(a>='a'&&a<='z')return a-'a' 10;
if(a>='A'&&a<='Z')return a-'A' 36;
return 0;
}
int dx[]={0,0,-1,1};
int dy[]={-1,1,0,0};
class SurroundingGame
{
public:
int maxScore(vector <string> cost, vector <string> benefit)
{
int i,j,k,x,y,n=cost.size(),m=cost[0].size(),sum=0;
prepare(n*m*2 2,0,n*m*2 1);
for(i=0;i<n; i)
for(j=0;j<m; j)
{
sum =get(benefit[i][j]);
if((i j)%2)
{
addedge(src,i*m j 1,get(cost[i][j]));
addedge(i*m j 1,n*m i*m j 1,get(benefit[i][j]));
}
else
{
addedge(n*m i*m j 1,i*m j 1,get(benefit[i][j]));
addedge(i*m j 1,dest,get(cost[i][j]));
}
for(k=0;k<4; k)
{
x=i dx[k];
y=j dy[k];
if(x<0||x>=n||y<0||y>=m)continue;
if((i j)%2)addedge(n*m i*m j 1,x*m y 1,oo);
else addedge(x*m y 1,n*m i*m j 1,oo);
}
}
sum-=Dinic_flow();
return sum;
}
// BEGIN CUT HERE
public:
void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); }
private:
template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
void test_case_0() { string Arr0[] = {"21","12"}; vector <string> Arg0(Arr0, Arr0 (sizeof(Arr0) / sizeof(Arr0[0]))); string Arr1[] = {"21","12"}; vector <string> Arg1(Arr1, Arr1 (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 4; verify_case(0, Arg2, maxScore(Arg0, Arg1)); }
void test_case_1() { string Arr0[] = {"ZZ","ZZ"}; vector <string> Arg0(Arr0, Arr0 (sizeof(Arr0) / sizeof(Arr0[0]))); string Arr1[] = {"11","11"}; vector <string> Arg1(Arr1, Arr1 (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 0; verify_case(1, Arg2, maxScore(Arg0, Arg1)); }
void test_case_2() { string Arr0[] = {"XXX","XXX","XXX"}; vector <string> Arg0(Arr0, Arr0 (sizeof(Arr0) / sizeof(Arr0[0]))); string Arr1[] = {"aaa","aZa","aaa"}; vector <string> Arg1(Arr1, Arr1 (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 2; verify_case(2, Arg2, maxScore(Arg0, Arg1)); }
void test_case_3() { string Arr0[] = {"asam","atik"}; vector <string> Arg0(Arr0, Arr0 (sizeof(Arr0) / sizeof(Arr0[0]))); string Arr1[] = {"123A","45BC"}; vector <string> Arg1(Arr1, Arr1 (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 71; verify_case(3, Arg2, maxScore(Arg0, Arg1)); }
void test_case_4() { string Arr0[] = {"IIIIIIII",
"IIWWWWII",
"IIWIIIII",
"IIWIIIII",
"IIWWWWII",
"IIIIIWII",
"IIIIIWII",
"IIWWWWII",
"IIIIIIII"}
; vector <string> Arg0(Arr0, Arr0 (sizeof(Arr0) / sizeof(Arr0[0]))); string Arr1[] = {"IIIIIIII",
"II0000II",
"II0II0II",
"II0II0II",
"II0000II",
"II0II0II",
"II0II0II",
"II0000II",
"IIIIIIII"}
; vector <string> Arg1(Arr1, Arr1 (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 606; verify_case(4, Arg2, maxScore(Arg0, Arg1)); }
// END CUT HERE
};
// BEGIN CUT HERE
int main()
{
SurroundingGame ___test;
___test.run_test(-1);
return 0;
}
// END CUT HERE
写评论
很抱歉,必須登入網站才能發佈留言。