2014 编程之美

第一题同构不会。


第二题比较容易,用总的情况减去有两个一样的情况,然后每次算乘法之前对 10^9+7取模

#include <stdio.h>
#include <string.h>


long long limit = 1000000007;
int main()
{
int testcase;
scanf("%d", &testcase);
for(int i = 1; i <= testcase; i++)
{
long long  n;
scanf("%lld", &n);
if(n >= limit)
n = n%limit;
long long t = n*(n+1)/2;
long long right = t-2*n+2;
if(right >= limit)
right = right%limit;
if(t >= limit)
t = t%limit;
long long left = t*t;
if(left >= limit)
left = left%limit;
long long res = left * right;
if(res >= limit)
res = res%limit;
printf("Case %d: %lld\n", i, res); 
}
}


第三题 据说要用匈牙利算法,表示没有学过,用的dfs+剪枝 AC了

#include <stdio.h>
#include <string.h>


#define MAXSIZE 101
int used[MAXSIZE][MAXSIZE];
unsigned int mat[MAXSIZE][MAXSIZE];
int M, N;
int pointofRow[MAXSIZE];
int pointofCol[MAXSIZE];
int cantUseRow[MAXSIZE];
int cantUseCol[MAXSIZE];
unsigned int minSum = 0xffffffff;


struct point
{
int x;
int y;
};


int avail(int m, int n)
{
if(cantUseCol[n])
return 0;
if(pointofRow[m] > 0 && pointofCol[n] > 0)
return 0;
return 1;
}


int findNext(int m, int n, struct point *next)
{
int i = 0;
if(!cantUseRow[m])
{
for(i = n+1; i < N; i++)
{
if(avail(m, i))
{
next->x = m;
next->y = i;
return 0;
}
}
}
if(m == M-1)
{
next->x = M;
next->y = N;
return -1;
}
for(i = 0; i < N; i++)
{
if(avail(m+1, i))
{
next->x = m+1;
next->y = i;
return 0;
}
}
return -1;
}


void dfs(int m, int n, int sum)
{
int i = m;
int j = n;
struct point next ={0, 0};
while(findNext(i, j, &next) != -1)
{
i = next.x;
j = next.y;
if(i - m > 1)
return;
int tmpcantUseColm = cantUseCol[m];
int tmpcantUseColn = cantUseCol[j];
if(m == i)
{
cantUseCol[m] = cantUseCol[j] = 1;
}
int tmpcantUseRow[MAXSIZE] = {0};
memcpy(tmpcantUseRow, cantUseRow, sizeof(cantUseRow));
int k = 0;
for(; k < i; k++)
{
if(used[k][j])
{
cantUseRow[k] = cantUseRow[i] = 1;
}
}


used[i][j] = 1;
pointofRow[i]++;
pointofCol[j]++;
dfs(i, j, sum + mat[i][j]);
used[i][j] = 0;
pointofRow[i]--;
pointofCol[j]--;
cantUseCol[m] = tmpcantUseColm;
cantUseCol[j] = tmpcantUseColn;
memcpy(cantUseRow, tmpcantUseRow, sizeof(cantUseRow));
}
if(next.x == M && next.y  == N && m == M-1)
{
int flag = 1;
int t = 0;
for(; t < N; t++)
flag = flag && pointofCol[t];
if(sum < minSum && flag)
minSum = sum;
}
}


int main()
{
int testcase;
int i, j, t;
scanf("%d", &testcase);
for(t = 1; t <= testcase; t++)
{
scanf("%d%d", &M, &N);
memset(mat, 0, sizeof(mat));
memset(used, 0, sizeof(used));
memset(pointofRow, 0, sizeof(pointofRow));
memset(pointofCol, 0, sizeof(pointofCol));
memset(cantUseCol, 0, sizeof(cantUseCol));
memset(cantUseRow, 0, sizeof(cantUseRow));
minSum = 0xffffffff;
for(i = 0; i < M; i++)
{
for(j = 0; j < N; j++)
{
scanf("%d", &mat[i][j]);
}
}
for(i = 0; i < N; i++)
{
used[0][i] = 1;
pointofRow[0]++;
pointofCol[i]++;
dfs(0, i, mat[0][i]);
used[0][i] = 0;
pointofRow[0]--;
pointofCol[i]--;
}
printf("Case %d: %d\n", t, minSum);
}
}



谁能给个同构的做法,完全不懂 = = 是图里面的东西吗...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值