Codeforces Round #155 (Div. 2)

题目:http://www.codeforces.com/contest/254

D:任意找一个R点bfs找到能炸死它的位置,枚举所有位置,对于位置A,再找一个A炸不到的R点,bfs找到能炸死它的所有位置,再枚举位置,对于枚举的位置B,判断一下A,B能不能炸死所有的老鼠。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<iostream>
using namespace std;
typedef long long ll;
const int inf = 1 << 29;
#define N 1010

char a[N][N];

struct node{
	int x,y;
	int step;
};
int dd[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int n,m;
int vis[20][20];
vector<pair<int,int> > e[2];
set<pair<int,int> > S,ans;
void bfs(int si,int sj,int d,int k)
{
	node t,tt;
	queue<node> qu;
	t.x=si,t.y=sj;t.step=0;
	memset(vis,0,sizeof(vis));
	vis[d][d]=1;
	qu.push(t);
	while(!qu.empty()){
		t=qu.front();qu.pop();
		if (k==1) {
			if (a[t.x][t.y] != 'X') {
				e[0].push_back(make_pair(t.x, t.y));
			}
		}else if(k==0){
			if (a[t.x][t.y] == 'R')
				S.insert(make_pair(t.x, t.y));
		}else if(k==2){
			if (a[t.x][t.y] != 'X')
				e[1].push_back(make_pair(t.x, t.y));
		}
		else if (k == 3) {
			if (a[t.x][t.y] == 'R')
				ans.insert(make_pair(t.x, t.y));
		}
		if(t.step>=d) continue;
		tt.step=t.step+1;
		for(int i=0;i<4;i++){
			tt.x=t.x+dd[i][0];
			tt.y=t.y+dd[i][1];
			if(tt.x<0||tt.x>=n||tt.y<0||tt.y>m) continue;
			if(a[tt.x][tt.y]=='X') continue;
			if(vis[tt.x-si+d][tt.y-sj+d]) continue;
			vis[tt.x-si+d][tt.y-sj+d]=1;
			qu.push(tt);
		}

	}
}
vector<pair<int,int> > R;

int main() {
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	int d;
	scanf("%d%d%d",&n,&m,&d);
	for(int i=0;i<n;i++)
		scanf("%s",a[i]);
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++) {
			if (a[i][j] == 'R') {
				R.push_back(make_pair(i,j));
			}
		}

	bfs(R[0].first,R[0].second,d,1);
	for(int i=0;i<(int)e[0].size();i++){
		S.clear();
		bfs(e[0][i].first, e[0][i].second, d,0);
		e[1].clear();
		if (S.size() == R.size()) {
			for (int j = 0; j < n; j++)
				for (int k = 0; k < m; k++) {
					if ((j != e[0][i].first || k != e[0][i].second)
							&& a[j][k] != 'X') {
						printf("%d %d %d %d\n", e[0][i].first+1, e[0][i].second+1,j+1, k+1);
						return 0;
					}
				}
		}
		for(int j=1;j<(int)R.size();j++){
			if(S.find(R[j])==S.end()){
				bfs(R[j].first,R[j].second,d,2);
				break;
			}
		}
		for(int j=0;j<(int)e[1].size();j++){
			ans.clear();
			for(set<pair<int,int> >::iterator it=S.begin();it!=S.end();it++)
				ans.insert(*it);
			bfs(e[1][j].first, e[1][j].second, d,3);
			if(ans.size()==R.size()){
				printf("%d %d %d %d\n",e[0][i].first+1,e[0][i].second+1,e[1][j].first+1, e[1][j].second+1);
				return 0;
			}
		}
	}
	printf("-1\n");
}


E:dp题,dp[i][j]表示i天过后还剩j数量的食物时的最大值,对于第i天枚举朋友数进行转移,记录路径输出


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<iostream>
using namespace std;
typedef long long ll;
const int inf = 1 << 29;

int a[410];
vector<pair<int,int> > e[410];
int pre[410][410];
int op[410][410];
int dp[410][410];

void output(int i,int n)
{
	if(!i) return;
	output(i-1,pre[i][n]);
	int k=op[i][n];
	printf("%d",k);
	for(int j=0;j<k;j++){
		printf(" %d",e[i][j].second);
	}
	puts("");
}

int cost[410][410];
int main() {
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	int n,v,m,l,r,f;
	scanf("%d%d",&n,&v);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	scanf("%d",&m);
	for(int i=0;i<m;i++){
		scanf("%d%d%d",&l,&r,&f);
		for(int j=l;j<=r;j++){
			e[j].push_back(make_pair(f,i+1));
		}

	}
	for(int i=1;i<=n;i++){
		sort(e[i].begin(),e[i].end());
		for(int j=0;j<(int)e[i].size();j++){
			cost[i][j+1]=cost[i][j]+e[i][j].first;
		}
	}
	memset(dp,-1,sizeof(dp));
	dp[0][0]=0;
	for(int i=0;i<n;i++){
		for(int j=0;j<=a[i];j++){
			if(dp[i][j]==-1) continue;
			int t=j+a[i+1];
			for(int k=0;k<=(int)e[i+1].size();k++){
				if(cost[i+1][k]+v>t) break;
				int tt=t-cost[i+1][k]-v;
				tt=min(tt,a[i+1]);
				if(dp[i+1][tt]<k+dp[i][j]){
					dp[i+1][tt]=k+dp[i][j];
					pre[i+1][tt]=j;
					op[i+1][tt]=k;
				}
			}
		}
	}
	int ans=-1,pos;
	for(int i=0;i<=a[n];i++){
		if(ans<dp[n][i]){
			ans=dp[n][i];
			pos=i;
		}
	}
	printf("%d\n",ans);
	output(n,pos);
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值