contest 链接:http://codeforces.com/gym/101673
求多个多边形并的面积,板子题,记小本本
#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
typedef long long ll;
const double inf=1e200;
const double eps=1e-12;
const double pi=4*atan(1.0);
int dcmp(double x){ return fabs(x)<eps?0:(x<0?-1:1);}
struct point{
double x,y;
point(double a=0,double b=0):x(a),y(b){}
};
point operator +(point A,point B) { return point(A.x+B.x,A.y+B.y);}
point operator -(point A,point B) { return point(A.x-B.x,A.y-B.y);}
point operator *(point A,double p){ return point(A.x*p,A.y*p);}
point operator /(point A,double p){ return point(A.x/p,A.y/p);}
bool operator ==(const point& a,const point& b){
return fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps;
}
double dot(point A,point B){ return A.x*B.x+A.y*B.y;}
double det(point A,point B){ return A.x*B.y-A.y*B.x;}
double det(point O,point A,point B){ return det(A-O,B-O);}
double length(point A){ return sqrt(dot(A,A));}
double area(vector<point>p){
double ans=0; int sz=p.size();
for(int i=1;i<sz-1;i++) ans+=det(p[i]-p[0],p[i+1]-p[0]);
return ans/2.0;
}
double seg(point O,point A,point B){
if(dcmp(B.x-A.x)==0) return (O.y-A.y)/(B.y-A.y);
return (O.x-A.x)/(B.x-A.x);
}
vector<point>pp[110];
pair<double,int>s[110*60];
double polyunion(vector<point>*p,int N){
double res=0;
for(int i=0;i<N;i++){
int sz=p[i].size();
for(int j=0;j<sz;j++){
int m=0;
s[m++]=mp(0,0);
s[m++]=mp(1,0);
point a=p[i][j],b=p[i][(j+1)%sz];
for(int k=0;k<N;k++){
if(i!=k){
int sz2=p[k].size();
for(int ii=0;ii<sz2;ii++){
point c=p[k][ii],d=p[k][(ii+1)%sz2];
int c1=dcmp(det(b-a,c-a));
int c2=dcmp(det(b-a,d-a));
if(c1==0&&c2==0){
if(dcmp(dot(b-a,d-c))){
s[m++]=mp(seg(c,a,b),1);
s[m++]=mp(seg(c,a,b),-1);
}
}
else{
double s1=det(d-c,a-c);
double s2=det(d-c,b-c);
if(c1>=0&&c2<0) s[m++]=mp(s1/(s1-s2),1);
else if(c1<0&&c2>=0) s[m++]=mp(s1/(s1-s2),-1);
}
}
}
}
sort(s,s+m);
double pre=min(max(s[0].first,0.0),1.0),now,sum=0;
int cov=s[0].second;
for(int j=1;j<m;j++){
now=min(max(s[j].first,0.0),1.0);
if(!cov) sum+=now-pre;
cov+=s[j].second;
pre=now;
}
res+=det(a,b)*sum;
}
}
return res/2;
}
int main()
{
int N,M,i,j; point tp;
scanf("%d",&N);
for(i=0;i<N;i++){
scanf("%d",&M);
for(j=0;j<M;j++){
scanf("%lf%lf",&tp.x,&tp.y);
pp[i].push_back(tp);
}
}
double t1=0,t2=polyunion(pp,N);
for(i=0;i<N;i++) t1+=area(pp[i]);
printf("%.7lf %.7lf\n",-t1,-t2);
return 0;
}
很水的小模拟
在不知道题意的情况下听队友说步骤就过了
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define PII pair<int, int>
#define all(x) x.begin(), x.end()
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e3 + 5;
using namespace std;
int main()
{
string s;
cin >> s;
int len = s.size();
int sum = 0;
for(int i = 0; i < len / 2; i++){
sum += s[i] - 'A';
}
for(int i = 0; i < len / 2; i++){
s[i] = (s[i] - 'A' + sum) % 26 + 'A';
}
sum = 0;
for(int i = len / 2; i < len; i++){
sum += s[i] - 'A';
}
for(int i = len / 2; i < len; i++){
s[i] = (s[i] - 'A' + sum) % 26 + 'A';
}
for(int i = 0; i < len / 2; i++){
s[i] = (s[i] - 'A' + s[i+len/2] - 'A') % 26 + 'A';
}
for(int i = 0; i < len / 2; i++){
cout << s[i];
}
cout << endl;
return 0;
}
这也是个水题啊,用栈模拟一下就好了
但还是因为取模没考虑负数WA了两发
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define PII pair<int, int>
#define all(x) x.begin(), x.end()
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e3 + 5;
using namespace std;
stack<int> st;
int main()
{
int n, k;
cin >> n >> k;
for(int i = 1; i <= k; i++){
string s; cin >> s;
if(s == "undo"){
int cnt;
cin >> cnt;
while(cnt--){
st.pop();
}
}
else{
stringstream ss;
ss << s;
int x;
ss >> x;
st.push(x);
}
}
int ans = 0;
while(!st.empty()){
ans += st.top();
st.pop();
}
cout << (ans + 3000 * n) % n << endl;
}
题意:求出黑色环的个数, 数据保证不相交
解题思路:其实也就是个简单的dfs,因为要判断环,多开一个vis数组标记一下即可
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define PII pair<int, int>
#define all(x) x.begin(), x.end()
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e3 + 5;
using namespace std;
char G[110][110];
int dir[8][2] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1} };
bool vis1[110][110], vis2[110][110];
int n, m;
int startx, starty;
int ans;
bool check(int x, int y){
if(x >= 1 && x <= n & y >= 1 && y <= m && G[x][y] == '#' && !vis1[x][y] & ! vis2[x][y]) return true;
return false;
}
void dfs(int x, int y, int cnt){
bool flag = false;
for(int i = 0; i <= 7; i++){
int tx = x + dir[i][0], ty = y + dir[i][1];
if(check(tx, ty)){
vis1[tx][ty] = vis2[tx][ty] = 1;
dfs(tx, ty, cnt + 1);
vis1[tx][ty] = 0;
flag = true;
}
}
if(!flag && cnt > 1)
for(int i = 0; i <= 7; i++){
int tx = x + dir[i][0], ty = y + dir[i][1];
if(tx == startx && ty == starty){
ans++;
return;
}
}
}
int main()
{
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
scanf(" %c", &G[i][j]);
}
}
ans = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(!vis1[i][j] && G[i][j] == '#'){
memset(vis1, 0, sizeof(vis1));
vis1[i][j] = vis2[i][j] = true;
startx = i, starty = j;
dfs(i, j, 1);
}
}
}
printf("%d\n", ans);
return 0;
}
好啦,无脑题都说完啦
G - A Question of Ingestion |
题目大意:一开始的食量为m,有n个连续的小时,每小时都有一个a[i]表示,可以选择吃或者不吃。
这个小时吃的话下个小时的食量就变成2/3,上个小时吃了这个小时不吃的话下个小时恢复到上个小时的,连续两小时不吃就能恢复到m
解题思路:开始题意理解错了,这么简单的一个记忆化搜索都没做出来,伤心。。
直接记忆化搜索枚举不吃的小时即可
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define PII pair<int, int>
#define all(x) x.begin(), x.end()
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;
int a[105];
int dp[105][20005];
int n, m;
int dfs(int i, int j){
if(i > n) return 0;
if(dp[i][j] != -1) return dp[i][j];
dp[i][j] = min(a[i], j) + max(dfs(i + 1, j * 2 / 3), max(dfs(i + 2, j), dfs(i + 3, m)));
return dp[i][j];
}
int main()
{
memset(dp, -1, sizeof(dp));
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++){
scanf("%d", a + i);
a[i] = min(a[i], m);
}
int ans = 0;
for(int i = 1; i <= n; i++){
ans = max(ans, dfs(i, m));
}
printf("%d\n", ans);
return 0;
}
还有一种dp写法:
dp[i][j] : 在第i个小时已经吃了j小时,获得的最大价值
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define PII pair<int, int>
#define all(x) x.begin(), x.end()
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;
int n, m;
int a[105], val[105];
int dp[105][105];
int main()
{
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++){
scanf("%d", a + i);
}
val[1] = m;
for(int i = 2; i <= n; i++){
val[i] = val[i-1] * 2 / 3;
}
for(int i = 1; i <= n; i++){
dp[i][1] = min(a[i], val[1]);
}
int ans = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= i; j++){
if(i >= 1) dp[i][j] = max(dp[i][j], dp[i-1][j-1] + min(val[j], a[i]));
if(i >= 2) dp[i][j] = max(dp[i][j], dp[i-2][j] + min(val[j], a[i]));
if(i >= 3) dp[i][1] = max(dp[i][1], dp[i-3][j] + min(val[1], a[i]));
ans = max(ans, dp[i][j]);
}
ans = max(ans, dp[i][1]);
}
printf("%d\n", ans);
return 0;
}
Continuing...
================================================================================
update:
题目大意:给n条边,然后去掉一个影响最大的点(数据保证有且仅有一个),让你先求出当前没有联通的点的对数,再让你加一条边,求出加了之后最少的没有联通的点的对数。
解题思路:对于第一问,直接枚举删的点,维护最大值并且记录下来
对于第二问,肯定是把最大的两块合起来,一个dfs就可以解决了
身为一个菜鸡,这题妙处真的多,多说几句。
首先,很容易想到如果能够得到每一个节点作为根节点它的子树的大小,就很容易做出来了,但是这样的复杂度是n ^ 2的
那么这样考虑:边dfs边记录、更新答案。
用一个sz数组保存以0为根节点,每个点子树的大小。那么vector里面装它接下来子树的大小,那以前的怎么办呢?很巧妙的用了一个sum记录了dfs下去的和,那么n - sum就是之前的了。那么接下来,如何利用这个vector来判断不连通的点的对数呢?
比如有三个数:1, 2, 3
res = 2 * 1 + 3 * (1 + 2) = 11
验证一下: res = (1 * (2 + 3) + 2 * (1 + 3) + 3 * (1 + 2)) / 2 = 11
这个结论真的太妙了,知道了也就能理解怎么推出来的了
这样,我们只需要一个dfs就能求出枚举所有点被删除的情况了
我真是个图论小白
#pragma GCC diagnostic error "-std=c++11"
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<ext/rope>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define PII pair<int, int>
#define all(x) x.begin(), x.end()
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e4 + 5;
using namespace std;
using __gnu_cxx::crope;
vector<int> G[maxn];
int sz[maxn];
int n;
ll maxv = 0, id = 0;
void dfs(int u, int fa){
sz[u] = 1;
vector<int> vec;
int sum = 0;
for(auto v : G[u]){
if(v == fa) continue;
dfs(v, u);
vec.pb(sz[v]);
sum += sz[v];
sz[u] += sz[v];
}
vec.pb(n - sum);
ll res = 0;
ll ss = 0;
for(auto i : vec){
res += ss * i;
ss += i;
}
if(res > maxv){
maxv = res;
id = u;
}
}
void dfs2(int u, int fa){
sz[u] = 1;
for(int i = 0; i < G[u].size(); i++){
int v = G[u][i];
if(v == fa) continue;
dfs2(v, u);
sz[u] += sz[v];
}
}
int main()
{
FAST;
cin >> n;
for(int i = 1; i <= n; i++){
int u, v; cin >> u >> v;
G[u].pb(v);
G[v].pb(u);
}
dfs(0, -1);
dfs2(id, -1);
vector<ll> vec;
for(int i = 0; i < G[id].size(); i++) vec.pb(sz[G[id][i]]);
if(vec.size() == 1) cout << 0 << ' ' << 0 << endl;
else{
sort(all(vec));
vec[vec.size()-2] += vec[vec.size()-1];
ll ss = 0, res = 0;
for(int i = 0; i < vec.size() - 1; i++){
res += ss * vec[i];
ss += vec[i];
}
cout << maxv << ' ' << res << endl;
}
return 0;
}
Continuing...