题目链接: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;
}