您的位置:首页 > 其它

2017.9.7 翻硬币 失败总结

2017-09-07 07:54 267 查看
这个题就是告诉你、越无从下手的题,越是数学和结论题、

这题搞了一下午+一晚上的时间,却连第一步都没想到、

因为这个题它每一个决策对其他点影响很大,所以直接从决策下手去讨论就显得非常有后效性。。

所以我们可以从关系入手、、把每个决策对其他有关决策的影响用式子表示出来

显然,对于每一个硬币,它所在的一行和所在的一列都会影响它、影响的效果是异或

所以如果最后全是0,他们的异或和是一个定值、、

就列出关系,然后就考虑怎么解

然后我们就需要消元,,这里有一个技巧:

由于n是偶数(比较后期的提示、),异或两次无效,所以我们考虑把一个点所在一行和一列的方程组写在一起、

注意到只有中间点有值、其他点都没动、

如:

0 0 0 1

1 0 1 0

0 0 0 1

0 1 0 0

考虑点 (2,3)

那我们把每个点的异或次数标上:

0(2) 0(2) 0(4) 1(2)

1(4) 0(4) 1(7) 0(4)

0(2) 0(2) 0(4) 1(2)

0(2) 1(2) 0(4) 0(2)

所以就只有(2,3)是奇数次

如果设每个点的决策为f(i,j)

那么这个点(2,3)就需要按f(2,1)^f(2,2)^f(2,3)^f(2,4)^f(1,3)^f(3,3)^f(3,4)次

所以扫一遍统计答案就可以了

所以我们考虑题有时需要根据决策入手,有时需要根据题目具有的关系入手、

根据决策入手可以考虑dp、网络流、贪心、dfs

根据关系入手可以考虑网络流、、还有这个奇怪的列方程消元、

有时候关系之间制约很明显的、有规律的就可以考虑列方程解决、、方程是把关系转化为具体的工具(就像一些解方程的题不能直观看出解一样)

%%ISA一眼秒

码(本来自己写的、后来发现可以求和优化、、就借(chao)鉴(xi)了):

#include<iostream>
#include<cstdio>
using namespace std;
char ch[1005];
int a[1005][1005],s1[1005],s2[1005],i,j,ans,n;
int main()
{
scanf("%d",&n);
for(i=0;i<n;i++)
{scanf("%s",ch);
for(j=0;j<n;j++)
{
a[i][j]=ch[j]-'0';
s1[i]^=a[i][j];
s2[j]^=a[i][j];
}
}
for(i=0;i<n;i++)
for(j=0;j<n;j++)
ans+=a[i][j]^s1[i]^s2[j];
printf("%d",min(ans,n*n-ans));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: