C - Ilya and Sticks N根木棍拼成的多个矩形,是面积最大,每根木棍最多可减去1的长度(5->4).sort下所以木棍然后贪心从长往短找就可以了
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
#define pi acos(-1.0)
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 100010;
ll a[N];
int main()
{
ll n;
while( cin >> n )
{
ll ans = 0;
for( int i = 1; i <= n; ++i )
cin >> a[i];
sort( a+1, a+1+n );
ll cur = 0;
for( int i = n-1; i >= 1; --i )
{
if( a[i+1] - a[i] <= 1 )
{
if( cur )
ans += a[i] * cur, cur = 0;
else
cur = a[i];
i--;
}
}
cout << ans << endl;
}
return 0;
}
D - Arthur and Walls 给出n*m的矩阵,求最少移除的×,使剩下的所有的‘.’都可以构成矩阵
有这么一种想法,假设某个点为×,那么如果该点的上面和左边都是'.',那么只要把这个点变成'.'就行了,但实际上这样不对,我们以1表示*,0表示'.',那么有一下这种情况
00100
00100
11011
00100
00100
在上面这种情况中无需改变任意的×。
换个角度想,在任意一个2*2的小矩阵中,假设某点在左下角,它的的上,右上,右都是'.',那么该点一定要改成'.',但是改变之后它会影响到周围的八个点,那么依次判断周围的八个点,只要是×那就扔进队列里迭代更新就行了
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
#define pi acos(-1.0)
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 2002;
char a[N][N];
int n, m;
queue < pair<int, int> > q;
int dir[8][2] = {
1, 0, -1, 0, 0, 1, 0, -1, 1, 1, 1, -1, -1, 1, -1, -1
};
bool check(int x, int y)
{
if(a[x][y] == '.' || x < 1 || y < 1 || x > n || y > m)
return 0;
if(a[x][y - 1] == '.' && a[x - 1][y - 1] == '.' && a[x - 1][y] == '.')
return 1;
if(a[x][y + 1] == '.' && a[x - 1][y + 1] == '.' && a[x - 1][y] == '.')
return 1;
if(a[x][y - 1] == '.' && a[x + 1][y - 1] == '.' && a[x + 1][y] == '.')
return 1;
if(a[x][y + 1] == '.' && a[x + 1][y + 1] == '.' && a[x + 1][y] == '.')
return 1;
return 0;
}
int main()
{
while(~scanf("%d%i", &n, &m))
{
while( !q.empty() )
q.pop();
for( int i = 1; i <= n; ++i )
scanf("%s", a[i] + 1 );
for( int i = 1; i <= n; ++i )
{
for( int j = 1; j <= m; ++j )
{
if( check( i, j ) )
q.push( make_pair(i, j) );
}
}
while( !q.empty() )
{
int x = q.front().first;
int y = q.front().second;
q.pop();
if( !check(x, y) )
continue;
a[x][y] = '.';
for( int i = 0; i < 8; ++i )
{
int xx = x + dir[i][0];
int yy = y + dir[i][1];
if( check(xx, yy) )
q.push(make_pair( xx, yy) );
}
}
for( int i = 1; i <= n; ++i )
puts(a[i]+1);
}
return 0;
}
E - Anya and Cubes n个数,最多可有k次操作,及使且最多使某个数变成原来的阶乘,问在不超过k次操作的情况下,选出的部分或者全部数的和为s。
注意到n最大只有25,而每个数最多有三种状态:不取,取原来的值,取其阶乘。那么一共是要3^25次状态,显然太大。这里用了一种叫折半枚举的方法,在dfs时先预处理出前一半数字的所有状态,然后在后一半的状态中查询是否有满足(前一半状态+后一半状态=答案)的情况出现,有就加入到方案数里面。详见代码。(注意LL,没看到wa了好几发)
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
#define pi acos(-1.0)
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 40;
ll fac[N], a[N];
map <int, ll> mp[N];
ll ans;
int n, k;
ll s;
void dfs( int pos, int usd, ll sum )
{
if( usd > k || sum > s )
return;
if( pos == n/2 )
{
++mp[usd][sum];
return;
}
dfs( pos+1, usd, sum );
dfs( pos+1, usd, sum + a[pos] );
if( a[pos] <= 18 )
dfs( pos+1, usd+1, sum + fac[ a[pos] ] );
}
void dfs1( int pos, int usd, int sum )
{
if( usd > k || sum > s )
return;
if( pos == n )
{
for( int i = 0; i + usd <= k; ++i )
{
if( mp[i].count( s-sum ) )
ans += mp[i][s-sum];
}
return;
}
dfs1( pos+1, usd, sum );
dfs1( pos+1, usd, sum + a[pos] );
if( a[pos] <= 18 )
dfs1( pos+1, usd+1, sum + fac[ a[pos] ] );
}
int main()
{
fac[0] = fac[1] = 1;
for( int i = 2; i <= 18; ++i )
fac[i] = i * fac[i-1];
while(~scanf("%d%d%I64d", &n, &k, &s))
{
for( int i = 0; i <= 30; ++i )
mp[i].clear();
for( int i = 0; i < n; ++i )
cin >> a[i];
dfs( 0, 0, 0 );
ans = 0;
dfs1( n/2, 0, 0 );
cout << ans << endl;
}
return 0;
}