题目链接:Click here~~
题意:
给n*m的矩阵,里面大部分写着数字,部分数字未给出,用-1表示,且每行每列未给出的数字不超过2个。然后给你每行需要满足的和与每列需要满足的和。
让你判断是否存在方案满足条件,如果满足,是否有多种。
解题思路:
先把每行(列)空1个的格子填好,填好后,判断其对应的列(行)是否出现矛盾。如果不矛盾,继续填。
当没有空1个格子的时候,就不用填了。
最后判断是否还有没有填好的格子,如果没有,则方案就是唯一的。
此题难点主要在于填空时对对应列(行)影响的处理上。
Ps:由于昨天脑子不太清醒,比赛时没有打出来,泪奔啊。
#include <stdio.h> #include <string.h> using namespace std; struct TT { int num,sum,SUM; int a[2]; }h[505],w[505]; int map[505][505]; bool fill(int x,int y) { bool two = false; if(h[x].num==1) { map[x][y] = h[x].SUM - h[x].sum; h[x].num = 0; h[x].sum = h[x].SUM; if(w[y].num==1) { w[y].num = 0; } else { two = true; w[y].num = 1; int tmp = w[y].a[0]^w[y].a[1]; w[y].a[0] = tmp^x; } w[y].sum += map[x][y]; } else { map[x][y] = w[y].SUM - w[y].sum; w[y].num = 0; w[y].sum = w[y].SUM; if(h[x].num==1) { h[x].num = 0; } else { two = true; h[x].num = 1; int tmp = h[x].a[0]^h[x].a[1]; h[x].a[0] = tmp^y; } h[x].sum += map[x][y]; } return two || h[x].sum==h[x].SUM && w[y].sum==w[y].SUM; } void test(int H,int W) { for(int i=1;i<=H;i++) { for(int j=1;j<=W;j++) { printf("%d ",map[i][j]); } printf("\n"); } } int main() { //freopen("Input","r",stdin); int z,H,W,ncase=0; bool no,one,flag; scanf("%d",&z); while(z--) { no = false; one = flag = true; memset(map,0,sizeof(map)); memset(h,0,sizeof(h)); memset(w,0,sizeof(w)); scanf("%d%d",&H,&W); for(int i=1;i<=H;i++) for(int j=1;j<=W;j++) { scanf("%d",&map[i][j]); if(map[i][j]>=0) { h[i].sum += map[i][j]; w[j].sum += map[i][j]; } else { h[i].a[ h[i].num ] = j; h[i].num ++; w[j].a[ w[j].num ] = i; w[j].num ++; } } for(int i=1;i<=H;i++) scanf("%d",&h[i].SUM); for(int j=1;j<=W;j++) scanf("%d",&w[j].SUM); while(flag) { flag = false; for(int i=1;i<=H;i++) if(h[i].num==1) { flag = true; if(!fill(i,h[i].a[0])) { //printf("%d %d-->out\n",i,h[i].a[0]); no = true; goto END; } } for(int j=1;j<=W;j++) if(w[j].num==1) { flag = true; if(!fill(w[j].a[0],j)) { //printf("%d %d-->out\n",w[j].a[0],j); no = true; goto END; } } } //test(H,W); END: printf("Case #%d: ",++ncase); if(no) puts("No solution"); else { for(int i=1;i<=H;i++) if(h[i].num) { one = false; break; } if(one) { for(int j=1;j<=W;j++) if(w[j].num) { one = false; break; } } puts(one?"Unique":"More than one"); } } return 0; }