题目:https://www.luogu.com.cn/problem/P2392
#include
using namespace std;
const int maxn = 25;
/*
枚举每道题交给哪边的脑子解决,找到两边时间较大值的最小值
*/
int s[5];//每个科目的题目数量
int tim[maxn][5];//完成每道题的时间
int Left,Right,minn,ans;
void dfs(int index,int y){
if(index > s[y]){
minn = min(minn,max(Left,Right));
return;
}
Left +=tim[index][y];
dfs(index+1,y);
Left -=tim[index][y];
Right +=tim[index][y];
dfs(index+1,y);
Right -=tim[index][y];
}
int main(){
scanf("%d %d %d %d",&s[1],&s[2],&s[3],&s[4]);
for(int i =1;i<=4;i++){
Left = Right = 0;
minn = 0x3fffff;
for(int j =1;j<=s[i];j++){
cin >> tim[j][i];
}
dfs(1,i);
ans += minn;
}
cout<< ans;
return 0;
}
#include
using namespace std;
const int maxn = 410;
int G[maxn][maxn];
bool vis[maxn][maxn]={false};
int n,m,stx,sty;
struct point{
int x,y;
point(int xx,int yy){
x =xx;
y =yy;
}
};
int dis[8][2] = {{1,2},{-1,2},{1,-2},{-1,-2},
{2,1},{2,-1},{-2,1},{-2,-1}};//马可以走的方向
void bfs(int sx,int sy){//下标从1开始
G[sx][sy] = 0;
queue<point> q;
q.push(point(sx,sy));
vis[sx][sy] = true;
while(!q.empty()){
point p = q.front();
q.pop();
for(int i =0;i<8;i++){
int nx = p.x+dis[i][0];
int ny = p.y+dis[i][1];
if(nx>0&&nx<=n&&ny>0&&ny<=m){//无越界
if(vis[nx][ny]==false){
q.push(point(nx,ny));
vis[nx][ny] = true;
G[nx][ny] = G[p.x][p.y]+1;
}
}
}
}
}
int main(){
memset(G,-1,sizeof(G));
cin >>n>>m>>stx>>sty;
bfs(stx,sty);
for(int i =1;i<=n;i++){
for(int j =1;j<=m;j++){
printf("%-5d",G[i][j]);
}
printf("\n");
}
return 0;
}
#include
using namespace std;
const int maxn = 310;
int ma[maxn][maxn],vis[maxn][maxn];//地图(存放砸陨石时间,标记是否走过该点
int m;//行星个数
int sx,sy,st;//陨石坐标及时间
int ans[maxn][maxn];//记录每个点的最小时间
int dis[5][2] = {{0,0},{0,1},{0,-1},{1,0},{-1,0}};//陨石四周
struct point{
int x, y;
point(int xx,int yy){
x = xx;
y = yy;
}
};
int check(int a){//判断路过该点时,是否有陨石降落
if(a==-1) return 0x3fffff;//没有
else return a;
}
int main(){
cin >> m;
memset(ma,-1,sizeof(ma));//陨石初始化为-1
for(int i =1;i<=m;i++){
cin>>sx>>sy>>st;
for(int j =0;j<5;j++){//在其及四周标记陨石
if(sx+dis[j][0]>=0 &&sy+dis[j][1]>=0&&(ma[sx+dis[j][0]][sy+dis[j][1]]==-1||ma[sx+dis[j][0]][sy+dis[j][1]]>st)){
ma[sx+dis[j][0]][sy+dis[j][1]] = st;
//如果xy坐标未出界且没有陨石砸落或砸落时间比输入时间晚,更新
}
}
}
queue<point> q;
vis[0][0] = 1;//标记初始点已经走过
q.push(point(0,0));//初始点入队
while(!q.empty()){
point temp = q.front();
q.pop();
if(ma[temp.x][temp.y] == -1){
printf("%d\n",ans[temp.x][temp.y]);
return 0;//如果该点安全,打印走到该点的时间
}
int news = ans[temp.x][temp.y]+1;//即将走的时间是现在点的下一s
for(int i =1;i<=4;i++){//向四周走一步
int xx = temp.x+dis[i][0];
int yy = temp.y+dis[i][1];
if(xx>=0&&yy>=0&&news<check(ma[xx][yy])&&vis[xx][yy]==0){
//如果新的点没有超边界,且陨石降落时间>现在的时间,且未走过
q.push(point(xx,yy));
vis[xx][yy] = 1;
ans[xx][yy] = news;//将该点时间放入数组
}
}
}
printf("-1\n");//出不了陨石区
return 0;
}
#include
using namespace std;
const int maxn = 25;
bool is_Su(int x){//判断是否是素数
int sqr = sqrt(x*1.0);
for(int i =2;i<sqr+1;i++){
if(x%i==0) return false;
}
return true;
}
int n,k,x[maxn],ans=0,ssum = 0;
bool vis[maxn]={false};
void dfs(int cnt,int startx,int ssum){//cnt已选个数 startx从哪开始选 ssum和
if(cnt == k){
if(is_Su(ssum)){
ans++;
}
return;
}
for(int i=startx;i<n;i++){
dfs(cnt+1,i+1,ssum+x[i]);
}
}
int main(){
memset(vis,0,sizeof(vis));
scanf("%d %d",&n,&k);
for(int i =0;i<n;i++){
scanf("%d",&x[i]);
}
dfs(0,0,0);
cout<<ans;
return 0;
}
#include
using namespace std;
const int maxn = 15;
int n,t[maxn],s[maxn];
int minabs=0x3fffff;
void dfs(int index,int sums,int sumt){//sums酸度,sumt甜度
if(index >n){
if(sums==1&&sumt==0) return;//清水
minabs = min(minabs,abs(sums-sumt));
return;
}
//分两种情况,一种是添加 2.不添加
dfs(index+1,sums*s[index],sumt+t[index]);
dfs(index+1,sums,sumt);
}
int main(){
scanf("%d",&n);
for(int i =1;i<=n;i++){
scanf("%d %d",&s[i],&t[i]);
}
dfs(1,1,0);
printf("%d\n",minabs);
return 0;
}
#include
using namespace std;
const int maxn = 20;
int n;
double a[20],b[20],dp[65000][20];//状压dp存距离
double ans=1e9;//10的9次方
bool vis[20];
double cal_dis(int x,int y){
return sqrt((a[x]-a[y])*(a[x]-a[y])+(b[x]-b[y])*(b[x]-b[y]));//距离公式
}
void dfs(int cnt,int now,double nowdis,int b){
//cnt吃的奶酪数,now当前在第几个奶酪的位置,nowdis距离,b用于状压
if(nowdis>ans) return;//剪枝
if(cnt == n){//吃够n个奶酪
ans = ans<nowdis ? ans:nowdis;
return;
}
for(int i =1;i<=n;i++){
if(vis[i]==false){
int p = b+(1<<(i-1));//状压存状态
if(dp[p][i]!=0 && dp[p][i]<=nowdis+cal_dis(now,i)) continue;//优化dp数组
vis[i] = true;
dp[p][i] = nowdis+cal_dis(now,i);
dfs(cnt+1,i,dp[p][i],p);
vis[i] = false;//回溯
}
}
}
int main(){
memset(vis,0,sizeof(vis));
scanf("%d",&n);//奶酪个数
for(int i =1;i<=n;i++){
scanf("%lf %lf",&a[i],&b[i]);
}
dfs(0,0,0,0);
printf("%.2f\n",ans);
return 0;
}
#include
using namespace std;
const int maxn = 25;
string str[maxn];
int n,maxlength=0,use[maxn];
char start;
int check(string str1,string str2){//计算重叠部分长度
for(int i =1;i<=min(str1.length(),str2.length());i++){//找出拼接长度
bool flag = true;
for(int j =0;j<i;j++){
if(str1[str1.length()-i+j]!=str2[j])//对应位数不相同
flag = false;
}
if(flag) return i;
}
return 0;//无重叠部分
}
void dfs(string nstr,int nlength){
maxlength = max(nlength,maxlength);
for(int i =0;i<n;i++){
if(use[i]<2){
int c = check(nstr,str[i]);
if(c>0){
use[i]++;
dfs(str[i],nlength+str[i].length()-c);
use[i]--;
}
}
}
}
int main(){
memset(use,0,sizeof(use));
scanf("%d",&n);
for(int i =0;i<=n;i++){
cin >> str[i];
}
dfs(str[n],1);//因为check函数要求
cout<<maxlength<<endl;
return 0;
}
#include
using namespace std;
const int maxn = 105;
struct point{
int x,y;
}p[maxn];//存储路径
char zimu[maxn][maxn];
int n;
int vis[maxn][maxn];//保存符合条件可见点
int dis[8][2]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,-1},{-1,1}};
char str[] ="yizhong";
void dfs(int index,point p[],int x,int y,int k){//方向已定
if(index==7){
for(int i =0;i<7;i++){
vis[p[i].x][p[i].y] = 1;//将路径上的点标志为可见
}
return;
}
else{
int nx = x+dis[k][0];
int ny = y+dis[k][1];
if(index == 6||zimu[nx][ny]==str[index+1]){
p[index].x = x;
p[index].y = y;
dfs(index+1,p,nx,ny,k);
}
}
}
int main(){
memset(vis,0,sizeof(vis));
scanf("%d",&n);
for(int i =0;i<n;i++){
cin >> zimu[i];
}
for(int i =0;i<n;i++){
for(int j =0;j<n;j++){
if(zimu[i][j]=='y'){//在y的周围找到紧挨的i
for(int k=0;k<8;k++){
int x = i+dis[k][0];
int y = j+dis[k][1];
if(zimu[x][y]=='i'){
dfs(0,p,i,j,k);//yi定下来之后遍历同方向k是否有接下来的字符串
}
}
}
}
}
for(int i=0;i<n;i++){
for(int j =0;j<n;j++){
if(vis[i][j]==1) printf("%c",zimu[i][j]);
else printf("*");
}
printf("\n");
}
return 0;
}
#include
using namespace std;
const int maxn = 7;
struct node{
string str;
int step;
node(string ss,int st){
str = ss;
step = st;
}
};
string A,B;
int cnt=0;//步数
string origin[maxn];//原来字符串
string newstr[maxn];//新转换字符串
set<string> vis;//判重
string exchange(string str,string substr,string rstr){//转换
string t = str;
if(str.find(substr)!=string::npos){
t.replace(t.find(substr),substr.length(),rstr);
}
return t;
}
void bfs(int n){
queue<node> q;
q.push(node(A,0));
while(!q.empty()){
node temp = q.front();
q.pop();
if(temp.str==B||temp.step>10){
cnt = temp.step;
return;
}
for(int i =0;i<n;i++){//遍历所有规则
string ns = exchange(temp.str,origin[i],newstr[i]);
if(!vis.count(ns)){
q.push(node(ns,temp.step+1));
vis.insert(ns);
}
}
}
}
int main(){
cin>>A;
cin>>B;
int n=0;
while(cin>>origin[n]>>newstr[n]){
n++;
}
bfs(n);
if(cnt>10||cnt==0)
cout<< "NO ANSWER!" <<endl;
else
cout <<cnt<<endl;
return 0;
}
#include
using namespace std;
const int maxn = 35;
int a[maxn][maxn],b[maxn][maxn];
int n;
int dis[4][2] ={{-1,0},{1,0},{0,1},{0,-1}};
void dfs(int x,int y){//将从xy开始的连通块染色
if(x<0||x>n+1||y<0||y>n+1||b[x][y]!=0){
return;
}
b[x][y] = 1;
for(int i =0;i<4;i++){
dfs(x+dis[i][0],y+dis[i][1]);
}
}
int main(){
scanf("%d",&n);
for(int i =1;i<=n;i++){
for(int j =1;j<=n;j++){
scanf("%d",&a[i][j]);
if(a[i][j]==0) b[i][j] = 0;
else b[i][j] = 2;
}
}
dfs(0,0);
for(int i =1;i<=n;i++){
for(int j=1;j<=n;j++){
if(b[i][j]==0) printf("2 ");
else printf("%d ",a[i][j]);
}
printf("\n");
}
return 0;
}