SGU 223. Little Kings

2024-03-24 08:48
文章标签 little 223 kings sgu

本文主要是介绍SGU 223. Little Kings,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原题:
223. Little Kings

time limit per test: 0.5 sec.
memory limit per test: 65536 KB
input: standard
output: standard

After solving nice problems about bishops and rooks, Petya decided that he would like to learn to play chess. He started to learn the rules and found out that the most important piece in the game is the king.

The king can move to any adjacent cell (there are up to eight such cells). Thus, two kings are in the attacking position, if they are located on the adjacent cells.

Of course, the first thing Petya wants to know is the number of ways one can position k kings on a chessboard of size n × n so that no two of them are in the attacking position. Help him!

Input

The input file contains two integers n (1 ≤ n ≤ 10) and k (0 ≤ k ≤ n2).

Output

Print a line containing the total number of ways one can put the given number of kings on a chessboard of the given size so that no two of them are in attacking positions.

Sample test(s)

Input
Test #1

3 2

Test #2

4 4

Output
Test #1

16

Test #2

79
大意:
给你一个尺寸为n×n的棋盘,上面放k个国王。每个国王的攻击范围为周围一圈的8个格。现在问你尺寸n×n的棋盘放k个国王有多少种放置方法。

//#include <bits/stdc++.h>
#include <iostream>
#include <cstring>
using namespace std;
//fstream in,out;
long long dp[11][1025][101];
int one[1025];//1的个数
int state[1025];//状态数
int n,k,index;
int TotalOne(int x)//计算一个二进制数里面有多少个1
{int coun=0;while(x){x=x&(x-1);coun++;}return coun;
}
bool LineCmp(int i)//判断一个状态(也就是棋盘上的一行)是否满足要求
{for(int j=1,k=1;j<=(1<<n);j=(1<<k),k++){if(j&i){if((j<<1)&i||(j>>1)&i)return false;}}return true;
}
void init()//初始化
{memset(dp,0,sizeof(dp));memset(one,0,sizeof(one));memset(state,0,sizeof(state));index=0;dp[0][1][0]=1;for(int i=0;i<=(1<<n)-1;i++)//找出一行能出现的所有状态,保存在state中//以及该状态有多少个1保存在one中{int tot=TotalOne(i);if(LineCmp(i)&&tot<=k&&tot<=(n+1)/2){++index;one[index]=TotalOne(i);//state[index]=i;}}
}
bool TwoLineCmp(int x,int y)//判断上面一行和下面一行是否冲突
{if(x&y||(y&(x>>1))||(y&(x<<1)))return false;return true;
}
int main()
{ios::sync_with_stdio(false);while(cin>>n>>k){init();
/*      for(int i=1;i<=index;++i)cout<<bitset<10>(state[i])<<" "<<one[i]<<endl;*/for(int i=1;i<=n;++i){for(int j=1;j<=index;++j){for(int kk=1;kk<=index;++kk){for(int l=0;l<=k;++l){if(l-one[j]>=0&&TwoLineCmp(state[j],state[kk]))dp[i][j][l]+=dp[i-1][kk][l-one[j]];}}}}long long ans=0;for(int i=1;i<=index;++i)ans+=dp[n][i][k];cout<<ans<<endl;}return 0;
}

解答:
教程上推荐的那个sgu上的题目,也是我的第一道sgu上面提交的题目。
刚刚接触状态压缩,转移方程还是挺好想的,dp[i][x][k]+=dp[i-1][y][k-one(x)]。
表示第i行在状态x下使用k个国王的摆放方式等于所有第i-1行状态y下使用k减去状态x用的国王数之和。这里的状态和数目都是保存在一个数组中!
我代码能力挺烂的,就没用递归来枚举所有状态。最后把所有计算到n行且国王用了k个的状态加在一起就是答案。

这篇关于SGU 223. Little Kings的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/841065

相关文章

【SGU】180. Inversions(归并排序求逆序数)

以前一般用树状数组和线段树做这种题 这次换个思路试试,归并排序! #include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;const int maxn = 111111;int n;int array[maxn];int tmp[maxn];L

【SGU】271. Book Pile(双端队列模拟)

一摞书,2个操作,一个操作是在书堆上加一本,第二个将前K个书翻转 看别人用Splay树做的,但是可以用双端队列模拟,因为K个书之后的书位置已经定下来了,所以只需要记录在队列头加书还是尾加书 #include<cstdio>#include<string>#include<algorithm>#include<queue>#include<stack>#include<cstrin

【SGU】115. Calendar 水题= =

传送门:【SGU】115. Calendar 题目分析:2001年1月1号星期1,然后就没什么好说的了= = 代码如下: #include <map>#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespac

【SGU】 114. Telecasting station 中位数

传送门:【SGU】 114. Telecasting station 题目分析:一个位置多个城市可以看成多个城市在同一位置,然后就可以求中位数了,易知最优的位置一定在中位数上。 代码如下 : #include <map>#include <vector>#include <cstdio>#include <cstring>#include <iostream>

【SGU】113. Nearly prime numbers 合数分解

传送门:【SGU】113. Nearly prime numbers 题目分析:O(sqrt(N))。。 代码如下: #include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std ;#define rep( i , a , b ) for

little knowledge及errno的一些错误定义

select()机制中提供一fd_set的数据结构,实际上是一long类型的数组,每一个数组元素都能与一打开的文件句柄(不管是socket句柄,还是其他文件或命名管道或设备句柄)建立联系,建立联系的工作由程序员完成,当调用select()时,由内核根据IO状态修改fd_set的内容,由此来通知执行了select()的进程哪一socket或文件发生了可读或可写事件。   LINUX 下宏定义

poj 3735 Training little cats(构造矩阵)

http://poj.org/problem?id=3735 大致题意: 有n只猫,开始时每只猫有花生0颗,现有一组操作,由下面三个中的k个操作组成: 1. g i 给i只猫一颗花生米 2. e i 让第i只猫吃掉它拥有的所有花生米 3. s i j 将猫i与猫j的拥有的花生米交换 现将上述一组操作循环m次后,问每只猫有多少颗花生? 很明显,要先构造矩阵,构造一个(n+1)

Codeforces Round #259 (Div. 2) D Little Pony and Harmony Chest

(比赛的时候全去想C了.... 预处理状压出每一个数的因数,然后用两数的状态相加与或 是非相同来判断是否互质 暴力枚举每一个数,记录出每一个状态最小的绝对值以及该位置的数 f[ i ][ 1<<j ] 前者表示第几位,后者表示状态,值表示在 绝对值的最小和 取n为最小绝对值的状态,再逆着找在数 </pre><pre name="code" class="cpp">#include <

Codeforces Round #259 (Div. 2) C Little Pony and Expected Maximum

用逆向思维解+容斥原理 最大为 m 个的概率为 1减去不是m最大的概率,(1 - (( m-1 )/ m ) ^ n ),则 m-1 的概率为 在 不是 m 的状态下 乘以 1减去不是m-1最大的概率 以此类推 感谢楠哥的思路 #include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#

力扣223题详解:矩形面积的多种解法与模拟面试

在本篇文章中,我们将详细解读力扣第223题“矩形面积”。通过学习本篇文章,读者将掌握如何使用多种方法来解决这一问题,并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释,以便于理解。 问题描述 力扣第223题“矩形面积”描述如下: 给你二维平面上两个由直线构成的矩形,请你计算并返回两个矩形覆盖的总面积。 每个矩形由其左下角的顶点和右上角的顶点表示:(A, B) 是第一个矩形的左