hdu 5386 Cover 脑洞 +有点贪心 2015 Multi-University Training Contest 8

来源:互联网 发布:血色残阳知乎 编辑:程序博客网 时间:2024/06/16 07:10

Cover

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1184    Accepted Submission(s): 411
Special Judge


Problem Description
You have an nn matrix.Every grid has a color.Now there are two types of operating:
L x y: for(int i=1;i<=n;i++)color[i][x]=y;
H x y:for(int i=1;i<=n;i++)color[x][i]=y;
Now give you the initial matrix and the goal matrix.There are m operatings.Put in order to arrange operatings,so that the initial matrix will be the goal matrix after doing these operatings

It's guaranteed that there exists solution.
 

Input
There are multiple test cases,first line has an integer T
For each case:
First line has two integer n,m
Then n lines,every line has n integers,describe the initial matrix
Then n lines,every line has n integers,describe the goal matrix
Then m lines,every line describe an operating

1color[i][j]n
T=5
1n100
1m500
 

Output
For each case,print a line include m integers.The i-th integer x show that the rank of x-th operating is i
 

Sample Input
13 52 2 1 2 3 3 2 1 3 3 3 3 3 3 3 3 3 3 H 2 3L 2 2H 3 3H 1 3L 2 3
 

Sample Output
5 2 4 3 1
 

Author
SXYZ
 

Source
2015 Multi-University Training Contest 8
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:  5395 5394 5393 5392 5391 

用顺序性解决问题,从开始状态考虑反而不好考虑,从结束情况倒推好考虑。
这是因为,如果从开始考虑,贴了一个,就会影响使用过的操作,可能会造成有些地方需要却不够。
如果从结果考虑,如果m个操作中某个位置没有出现过,那么那个位置一定不用贴,
如果出现过了,那么首先把符合最后情况的考虑进去,然后倒着考虑,这样最后的结果是对的,无论怎么贴贴过的位置都是符合的。
而且这样一定能保证正确:
1.首先这样贴是必须的,不论开始的状态如何,假如有某一行有n种贴法,现在有x种与结果不同,y种与结果相同,只要是把某种与结果不同的放到最后都是错的,所以一直要把所有的y全部放到最后才行  。(这是必须性)(ps:假如y=0,就一定有x=0,因为保证有解)
而且只要放了第一个y到最后,不论是哪一个操作,这个位置其余的随便贴。

2.
(一定有解性)题目说一定有解,就是说每个操作一定能安排一个恰当的位置,即使倒着考虑现在暂时不能贴,那以后也一定可以贴。
 (没有相互影响)因为每次操作是对同一行或同一列的多个位置贴,只要当前操作对某个位置不合适就不能贴,(这个操作一定有办法再之后贴进去,证明这个操作对某一个位置来说是x,那么一定有y,先贴y),先找能贴的贴。假如说没有一个操作能贴,那是不可能的,因为保证有解。
(所以某一操作能贴近去,它覆盖的所有位置必须与结果相同或是已经贴过了)
3.综合考虑,贴法是必须的,而且每个操作都一定能安排到一个合适的顺序位置,另加倒着想当前步一定有操作可做,那么这样做一定是正确的。

#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<climits>#include<queue>#include<vector>#include<map>#include<sstream>#include<set>#include<stack>#include<utility>#pragma comment(linker, "/STACK:102400000,102400000")#define PI 3.1415926535897932384626#define eps 1e-10#define sqr(x) ((x)*(x))#define FOR0(i,n)  for(int i=0 ;i<(n) ;i++)#define FOR1(i,n)  for(int i=1 ;i<=(n) ;i++)#define FORD(i,n)  for(int i=(n) ;i>=0 ;i--)#define  lson   num<<1,le,mid#define rson    num<<1|1,mid+1,ri#define MID   int mid=(le+ri)>>1#define zero(x)((x>0? x:-x)<1e-15)using namespace std;const int INF =0x3f3f3f3f;const int maxn= 100+10   ;const int maxm= 500+10   ;//const int INF=    ;typedef long long ll;const ll inf =1000000000000000;//1e15;//ifstream fin("input.txt");//ofstream fout("output.txt");//fin.close();//fout.close();//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);//by yskysker123int n,m;int st[maxn][maxn];int ed[maxn][maxn];int ans[maxm];struct kk{    char op;    int x;//x表示第x行或第x列    int y;    int id;//操作序号    kk () {}    kk (char o,int xx,int yy,int id_):op(o),x(xx),y(yy),id(id_){}    bool operator<(const kk x) const  //用set必须给出一个排序方法    {        return id<x.id;    }}  ;multiset< kk > se;int cnt;int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++)        {            for(int j=1;j<=n;j++)            {                scanf("%d",&st[i][j]);            }        }        for(int i=1;i<=n;i++)        {              for(int j=1;j<=n;j++)             {                 scanf("%d",&ed[i][j]);             }        }        int x,y;        char op;        for(int i=1;i<=m;i++)        {            scanf(" %c%d%d",&op,&x,&y);            se.insert(kk (op,x,y,i) );        }    cnt=m;    set<kk>::iterator  it;    while(!se.empty())    {        for(it=se.begin() ;  it!=se.end();it++)        {            int x=it->x;            int y=it->y;            int id=it->id;            if(it->op=='H')            {                int i;                for( i=1;i<=n;i++)                {                    if( !(ed[x][i]==0||ed[x][i]==y)  )    break;                }                if(i!=n+1)  continue;                for( i=1;i<=n;i++)                {                        ed[x][i]=0;                }                se.erase(it);                 ans[cnt--]=id;                break;            }            else            {                int i;                for( i=1;i<=n;i++)                {                    if(  !(ed[i][x]==0||ed[i][x]==y)   )  break;                }                if(i!=n+1)  continue;                for( i=1;i<=n;i++)                {                    ed[i][x]=0;                }                se.erase(it);                ans[cnt--]=id;                break;            }        }    }    printf("%d",ans[1]);    for(int i=2;i<=m;i++)    {        printf(" %d",ans[i]);    }    putchar('\n');    }    return 0;}


0 0
原创粉丝点击