七夕祭(贪心+分金币问题)

问题 M: 七夕祭

时间限制: 1 Sec  内存限制: 128 MB
提交: 75  解决: 20
[提交] [状态] [讨论版] [命题人:admin]

题目描述

七夕节因牛郎织女的传说而被扣上了「情人节」的帽子。于是TYVJ今年举办了一次线下七夕祭。Vani同学今年成功邀请到了cl同学陪他来共度七夕,于是他们决定去TYVJ七夕祭游玩。
TYVJ七夕祭和11区的夏祭的形式很像。矩形的祭典会场由N排M列共计N×M个摊点组成。虽然摊点种类繁多,不过cl只对其中的一部分摊点感兴趣,比如章鱼烧、苹果糖、棉花糖、射的屋……什么的。Vani预先联系了七夕祭的负责人zhq,希望能够通过恰当地布置会场,使得各行中cl感兴趣的摊点数一样多,并且各列中cl感兴趣的摊点数也一样多。不过zhq告诉Vani,摊点已经布置完毕了,唯一的调整方式就是交换两个相邻的摊点。两个摊点相邻,当且仅当他们处在同一行或者同一列的相邻位置上。由于zhq率领的TYVJ开发小组成功地扭曲了空间,每一行或每一列的第一个位置和最后一个位置也算作相邻。现在Vani想知道他的两个要求最多能满足多少个。在此前提下,至少需要交换多少次摊点。

 

输入

第一行包含三个整数N和M和T。T表示cl对多少个摊点感兴趣。
接下来T行,每行两个整数x,y,表示cl对处在第x行第y列的摊点感兴趣。

 

输出

首先输出一个字符串。如果能满足 Vani 的全部两个要求,输出 both;如果通过调整 只能使得各行中 cl 感兴趣的摊点数一样多,输出 row;如果只能使各列中 cl 感兴趣的摊点 数一样多,输出 column;如果均不能满足,输出 impossible。
如果输出的字符串不是 impossible, 接下来输出最小交换次数,与字符串之间用一 个空格隔开。

 

样例输入

2 3 4
1 3
2 1
2 2
2 3

 

样例输出

row 1

 

提示

对于30%的数据,N,M≤100。
对于70%的数据,N,M≤1000。
对于100%的数据,1≤N,M≤100000,0≤T≤min(NM,100000),1≤x≤N,1≤y≤M。

分析:这个题是均分纸牌,分金币的升级版。下面以分金币问题引入。

一、分金币:

1、题意:圆桌旁坐着n个人,每人有一定数量的金币,金币总数总能被n整除。每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数相等,你的任务是求出被转手的金币数量的最小值。

2、已知每个人初始情况下手中的金币数,那么总金币数MZ=X1+X2+X3+....+XN。最终每个人获得的金币就是M=MZ/N。

3、设整个交换过程中第n个人给第n-1个人共An枚金币,对于n=1时为第一人给第n个人金币数。

4、可得

x1-A1+A2=M; => A1=x1+A2-M;

x2-A2+A3=M; => A2=x2+A3-M;

x3-A3+A4=M; => A3=x3+A4-M;

x4-A4+A1=M; => A4=x4+A1-M;

5、X2=X1-(M-A1);

     X3=X2-(M-A2);

     X4=X3-(M-A3);

     X5=X4-(M-A4);

6、设

           x2=x1-C1;

           x3=x1-C2;

           x4=X1-C3;

           被转手的金币数量:ans=|x1|+|x2|+|x3|+|x4|........+|xn|=|x1-0|+|x1-C1|+|x1-C2|.....+|x1-Cn-1|。

(看不懂的,可以从4开始自己往6推一下)

7、问题就是就一个ans的最小值,就可以看作,一共n个点,找到一个点到其它各个点的距离之和最小,经典的货仓选址问题。

X1为C数组的中位数时ans最小。到这里就搞定了。

二、七夕祭

1、impossible的情况很简单,就是行数、列数都不是T的因数。

2、对于行和列互不影响,分开求,就是两个分金币问题。

3、如果n是T的因数,m也是T的因数,那么就是both。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
#define FAST_IO ios::sync_with_stdio(false)
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MAX=1e5+10;
const int mod=1e9+7;
typedef long long ll;
using namespace std;
#define gcd(a,b) __gcd(a,b)
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll qpow(ll a,ll b){ll r=1,t=a; while(b){if(b&1)r=(r*t)%mod;b>>=1;t=(t*t)%mod;}return r;}
inline ll inv1(ll b){return qpow(b,mod-2);}
inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll r=exgcd(b,a%b,y,x);y-=(a/b)*x;return r;}
inline ll read(){ll x=0,f=1;char c=getchar();for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;for(;isdigit(c);c=getchar()) x=x*10+c-'0';return x*f;}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
int n,m,t;
int row[MAX],col[MAX];
ll ans;
void solve_row()
{
    ll b[MAX],ave=0,mid;
    memset(b,0,sizeof(b));
    for(int i=1;i<=n;i++)
        ave+=row[i];
    ave/=n;
    for(int i=1;i<=n;i++)
        row[i]-=ave;

    for(int i=1;i<=n;i++)
        b[i]=b[i-1]+row[i];
    sort(b+1,b+1+n);
    mid=b[(n+1)/2];

    for(int i=1;i<=n;i++)
        ans+=abs(b[i]-mid);
}
void solve_col()
{
    ll b[MAX],ave=0,mid;
    memset(b,0,sizeof(b));
    for(int i=1;i<=m;i++)
        ave+=col[i];
    ave/=m;
    for(int i=1;i<=m;i++)
        col[i]-=ave;

    for(int i=1;i<=m;i++)
        b[i]=b[i-1]+col[i];
    sort(b+1,b+1+m);
    mid=b[(m+1)/2];

    for(int i=1;i<=m;i++)
        ans+=abs(b[i]-mid);
}
int main()
{
    scanf("%d%d%d",&n,&m,&t);
    for(int i=1;i<=t;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        row[x]++;
        col[y]++;
    }

    if(t%n && t%m)
    {
        printf("impossible\n");
        return 0;
    }
    if(t

 

你可能感兴趣的:(奇妙思维)